Commit feae79dd authored by xinzhedeai's avatar xinzhedeai

add:同步 from liqilin 1219

parent 47dfce11
...@@ -68,5 +68,7 @@ VITE_SERVICE_URL=http://192.168.2.53:9995 ...@@ -68,5 +68,7 @@ VITE_SERVICE_URL=http://192.168.2.53:9995
# 模型地址环境 # 模型地址环境
VITE_MODEL_URL=http://192.168.2.53:9995/model VITE_MODEL_URL=http://192.168.2.53:9995/model
# 开发环境 - WebSocket 全局地址 # 开发环境 - WebSocket 全局地址
# VITE_WEBSOCKET_URL=ws://192.168.3.248:9996 # VITE_WEBSOCKET_URL=ws://192.168.3.248:9996
\ No newline at end of file
...@@ -6,17 +6,13 @@ ...@@ -6,17 +6,13 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="color-scheme" content="light dark" /> <meta name="color-scheme" content="light dark" />
<!-- 外部 - 依赖库 -->
<!-- <script src="./public/js/proj4.js"></script>
<script src="./public/js/turf.min.js"></script>
<script src="./public/js/echarts.min.js"></script> -->
<!-- 外部 - 依赖库 --> <!-- 外部 - 依赖库 -->
<script src="./public/js/proj4.js"></script> <script src="./public/js/proj4.js"></script>
<script src="./public/js/turf.min.js"></script> <script src="./public/js/turf.min.js"></script>
<link rel="stylesheet" type="text/css" href="./Cesium/Widgets/widgets.css" /> <link rel="stylesheet" type="text/css" href="./Cesium/Widgets/widgets.css" />
<script type="text/javascript" src="/public/webrtcstreamer.js"></script>
<script type="text/javascript" src="./Cesium/Cesium.js"></script> <script type="text/javascript" src="./Cesium/Cesium.js"></script>
<script src="./public/codebase/webVideoCtrl.js"></script> <script src="/public/jquery-1.7.1.min.js"></script>
<script src="./public/jquery-1.7.1.min.js"></script>
<title>%VITE_APP_TITLE%</title> <title>%VITE_APP_TITLE%</title>
</head> </head>
......
...@@ -29,9 +29,15 @@ importers: ...@@ -29,9 +29,15 @@ importers:
'@sa/utils': '@sa/utils':
specifier: workspace:* specifier: workspace:*
version: link:packages/utils version: link:packages/utils
'@vicons/fa':
specifier: ^0.13.0
version: 0.13.0
'@vicons/fluent': '@vicons/fluent':
specifier: ^0.13.0 specifier: ^0.13.0
version: 0.13.0 version: 0.13.0
'@vicons/ionicons4':
specifier: ^0.13.0
version: 0.13.0
'@vueuse/core': '@vueuse/core':
specifier: 14.0.0 specifier: 14.0.0
version: 14.0.0(vue@3.5.22(typescript@5.9.3)) version: 14.0.0(vue@3.5.22(typescript@5.9.3))
...@@ -1455,9 +1461,15 @@ packages: ...@@ -1455,9 +1461,15 @@ packages:
cpu: [x64] cpu: [x64]
os: [win32] os: [win32]
'@vicons/fa@0.13.0':
resolution: {integrity: sha512-BFcDewcT78fSn4Y/fOgqlswbLUEW3+qJK2iJiNtgmkMzadBVpDXhNyVKsYM3V2uKPvDUrZT0JCWDWVRCiBXJZA==}
'@vicons/fluent@0.13.0': '@vicons/fluent@0.13.0':
resolution: {integrity: sha512-bYGZsOE3qzvm3Cm43e7tybgGlr5ZUpYqtRZq0g0Tfupe8jIzLolpvQLNUt1zS8Mgt6goTbUk5YH7Fkv16jkykg==} resolution: {integrity: sha512-bYGZsOE3qzvm3Cm43e7tybgGlr5ZUpYqtRZq0g0Tfupe8jIzLolpvQLNUt1zS8Mgt6goTbUk5YH7Fkv16jkykg==}
'@vicons/ionicons4@0.13.0':
resolution: {integrity: sha512-5WHIl/4R5a4i9GONa+hIQWxg/WczrbsCdqxawHZvdd3drsEr+Q3yzlfS+NNRO4WS3uDW2uWLCwoW+yp5TgcKeQ==}
'@vicons/ionicons5@0.13.0': '@vicons/ionicons5@0.13.0':
resolution: {integrity: sha512-zvZKBPjEXKN7AXNo2Na2uy+nvuv6SP4KAMQxpKL2vfHMj0fSvuw7JZcOPCjQC3e7ayssKnaoFVAhbYcW6v41qQ==} resolution: {integrity: sha512-zvZKBPjEXKN7AXNo2Na2uy+nvuv6SP4KAMQxpKL2vfHMj0fSvuw7JZcOPCjQC3e7ayssKnaoFVAhbYcW6v41qQ==}
...@@ -5441,8 +5453,12 @@ snapshots: ...@@ -5441,8 +5453,12 @@ snapshots:
'@unrs/resolver-binding-win32-x64-msvc@1.11.1': '@unrs/resolver-binding-win32-x64-msvc@1.11.1':
optional: true optional: true
'@vicons/fa@0.13.0': {}
'@vicons/fluent@0.13.0': {} '@vicons/fluent@0.13.0': {}
'@vicons/ionicons4@0.13.0': {}
'@vicons/ionicons5@0.13.0': {} '@vicons/ionicons5@0.13.0': {}
'@vitejs/plugin-vue-jsx@5.1.1(vite@7.1.12(@types/node@24.9.2)(jiti@2.6.1)(sass@1.93.3)(tsx@4.20.6)(yaml@2.8.1))(vue@3.5.22(typescript@5.9.3))': '@vitejs/plugin-vue-jsx@5.1.1(vite@7.1.12(@types/node@24.9.2)(jiti@2.6.1)(sass@1.93.3)(tsx@4.20.6)(yaml@2.8.1))(vue@3.5.22(typescript@5.9.3))':
......
(function() {
var Nr = 10;
// convert two-dimensional indicies to one-dim array indices
var I00 = 0;
var I01 = 1;
var I02 = 2;
var I03 = 3;
var I10 = 4;
var I11 = 5;
var I12 = 6;
var I13 = 7;
var I20 = 8;
var I21 = 9;
var I22 = 10;
var I23 = 11;
var I30 = 12;
var I31 = 13;
var I32 = 14;
var I33 = 15;
// S-Box substitution table
var S_enc = new Array(
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5,
0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0,
0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc,
0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a,
0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0,
0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b,
0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85,
0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5,
0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17,
0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88,
0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c,
0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9,
0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6,
0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e,
0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94,
0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68,
0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16);
// inverse S-Box for decryptions
var S_dec = new Array(
0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38,
0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87,
0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d,
0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2,
0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16,
0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda,
0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a,
0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02,
0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea,
0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85,
0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89,
0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20,
0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31,
0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d,
0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0,
0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26,
0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d);
function cvt_hex8 (val) {
var vh = (val>>>4)&0x0f;
return vh.toString(16) + (val&0x0f).toString(16);
}
function cvt_byte (str) {
// get the first hex digit
var val1 = str.charCodeAt(0);
// do some error checking
if (val1 >= 48 && val1 <= 57) {
// have a valid digit 0-9
val1 -= 48;
} else if (val1 >= 65 && val1 <= 70) {
// have a valid digit A-F
val1 -= 55;
} else if (val1 >= 97 && val1 <= 102) {
// have a valid digit A-F
val1 -= 87;
} else {
// not 0-9 or A-F, complain
console.log( str.charAt(1)+" is not a valid hex digit" );
return -1;
}
// get the second hex digit
var val2 = str.charCodeAt(1);
// do some error checking
if ( val2 >= 48 && val2 <= 57 ) {
// have a valid digit 0-9
val2 -= 48;
} else if ( val2 >= 65 && val2 <= 70 ) {
// have a valid digit A-F
val2 -= 55;
} else if ( val2 >= 97 && val2 <= 102 ) {
// have a valid digit A-F
val2 -= 87;
} else {
// not 0-9 or A-F, complain
console.log( str.charAt(2)+" is not a valid hex digit" );
return -1;
}
// all is ok, return the value
return val1*16 + val2;
}
// conversion function for non-constant subscripts
// assume subscript range 0..3
function I(x,y) {
return (x*4) + y;
}
// remove spaces from input
function remove_spaces(instr) {
var i;
var outstr = "";
for(i=0; i<instr.length; i++) {
if ( instr.charAt(i) != " " )
// not a space, include it
outstr += instr.charAt(i);
}
return outstr;
}
// get the message to encrypt/decrypt or the key
// return as a 16-byte array
function get_value(str, isASCII) {
var dbyte = new Array(16);
var i;
var val; // one hex digit
if (isASCII) {
// check length of data
if (str.length > 16) {
console.log("is too long, using the first 16 ASCII characters" );
}
// have ASCII data
// 16 characters?
if (str.length >= 16) {
// 16 or more characters
for(i=0; i<16; i++) {
dbyte[i] = str.charCodeAt(i);
}
} else {
// less than 16 characters - fill with NULLs
for(i=0; i<str.length; i++) {
dbyte[i] = str.charCodeAt(i);
}
for( i=str.length; i<16; i++) {
dbyte[i] = 0;
}
}
} else {
// have hex data - remove any spaces they used, then convert
//str = remove_spaces(str);
// check length of data
if ( str.length != 32 ) {
//console.log("\tget_value:\tstr = " + str + "\tisASCII = " + isASCII); //isASCII = false
console.log("length wrong: Is " + str.length + " hex digits, but must be 128 bits (32 hex digits)");
dbyte[0] = -1;
return dbyte;
}
for( i=0; i<16; i++ ) {
// isolate and convert this substring
dbyte[i] = cvt_byte( str.substr(i*2,2) );
if( dbyte[i] < 0 ) {
// have an error
dbyte[0] = -1;
return dbyte;
}
}
}
// return successful conversion
return dbyte;
}
//do the AES GF(2**8) multiplication
// do this by the shift-and-"add" approach
function aes_mul(a, b) {
var res = 0;
while(a > 0) {
if((a&1) != 0)
res = res ^ b; // "add" to the result
a >>>= 1; // shift a to get next higher-order bit
b <<= 1; // shift multiplier also
}
// now reduce it modulo x**8 + x**4 + x**3 + x + 1
var hbit = 0x10000; // bit to test if we need to take action
var modulus = 0x11b00; // modulus - XOR by this to change value
while(hbit >= 0x100) {
if ((res & hbit) != 0) {
res ^= modulus; // XOR with the modulus
}
// prepare for the next loop
hbit >>= 1;
modulus >>= 1;
}
return res;
}
// apply the S-box substitution to the key expansion
function SubWord(word_ary) {
var i;
for(i=0; i<16; i++) {
word_ary[i] = S_enc[word_ary[i]];
}
return word_ary;
}
// rotate the bytes in a word
function RotWord(word_ary) {
return new Array(word_ary[1], word_ary[2], word_ary[3], word_ary[0]);
}
// calculate the first item Rcon[i] = { x^(i-1), 0, 0, 0 }
// note we only return the first item
function Rcon(exp) {
var val = 2;
var result = 1;
// remember to calculate x^(exp-1)
exp--;
// process the exponent using normal shift and multiply
while ( exp > 0 )
{
if ( (exp & 1) != 0 )
result = aes_mul( result, val );
// square the value
val = aes_mul( val, val );
// move to the next bit
exp >>= 1;
}
return result;
}
// round key generation
// return a byte array with the expanded key information
function key_expand( key )
{
var temp = new Array(4);
var i, j;
var w = new Array(4*(Nr+1));
// copy initial key stuff
for( i=0; i<16; i++ )
{
w[i] = key[i];
}
// generate rest of key schedule using 32-bit words
i = 4;
while ( i < 4*(Nr+1)) // blocksize * ( rounds + 1 )
{
// copy word W[i-1] to temp
for( j=0; j<4; j++ )
temp[j] = w[(i-1)*4+j];
if ( i % 4 == 0)
{
// temp = SubWord(RotWord(temp)) ^ Rcon[i/4];
temp = RotWord( temp );
temp = SubWord( temp );
temp[0] ^= Rcon( i>>>2 );
}
// word = word ^ temp
for( j=0; j<4; j++ )
w[i*4+j] = w[(i-4)*4+j] ^ temp[j];
i++;
}
return w;
}
// do S-Box substitution
function SubBytes(state, Sbox)
{
var i;
for( i=0; i<16; i++ )
state[i] = Sbox[ state[i] ];
return state;
}
// shift each row as appropriate
function ShiftRows(state)
{
var t0, t1, t2, t3;
// top row (row 0) isn't shifted
// next row (row 1) rotated left 1 place
t0 = state[I10];
t1 = state[I11];
t2 = state[I12];
t3 = state[I13];
state[I10] = t1;
state[I11] = t2;
state[I12] = t3;
state[I13] = t0;
// next row (row 2) rotated left 2 places
t0 = state[I20];
t1 = state[I21];
t2 = state[I22];
t3 = state[I23];
state[I20] = t2;
state[I21] = t3;
state[I22] = t0;
state[I23] = t1;
// bottom row (row 3) rotated left 3 places
t0 = state[I30];
t1 = state[I31];
t2 = state[I32];
t3 = state[I33];
state[I30] = t3;
state[I31] = t0;
state[I32] = t1;
state[I33] = t2;
return state;
}
// inverset shift each row as appropriate
function InvShiftRows(state)
{
var t0, t1, t2, t3;
// top row (row 0) isn't shifted
// next row (row 1) rotated left 1 place
t0 = state[I10];
t1 = state[I11];
t2 = state[I12];
t3 = state[I13];
state[I10] = t3;
state[I11] = t0;
state[I12] = t1;
state[I13] = t2;
// next row (row 2) rotated left 2 places
t0 = state[I20];
t1 = state[I21];
t2 = state[I22];
t3 = state[I23];
state[I20] = t2;
state[I21] = t3;
state[I22] = t0;
state[I23] = t1;
// bottom row (row 3) rotated left 3 places
t0 = state[I30];
t1 = state[I31];
t2 = state[I32];
t3 = state[I33];
state[I30] = t1;
state[I31] = t2;
state[I32] = t3;
state[I33] = t0;
return state;
}
// process column info
function MixColumns(state)
{
var col;
var c0, c1, c2, c3;
for( col=0; col<4; col++ )
{
c0 = state[I(0,col)];
c1 = state[I(1,col)];
c2 = state[I(2,col)];
c3 = state[I(3,col)];
// do mixing, and put back into array
state[I(0,col)] = aes_mul(2,c0) ^ aes_mul(3,c1) ^ c2 ^ c3;
state[I(1,col)] = c0 ^ aes_mul(2,c1) ^ aes_mul(3,c2) ^ c3;
state[I(2,col)] = c0 ^ c1 ^ aes_mul(2,c2) ^ aes_mul(3,c3);
state[I(3,col)] = aes_mul(3,c0) ^ c1 ^ c2 ^ aes_mul(2,c3);
}
return state;
}
// inverse process column info
function InvMixColumns(state)
{
var col;
var c0, c1, c2, c3;
for( col=0; col<4; col++ )
{
c0 = state[I(0,col)];
c1 = state[I(1,col)];
c2 = state[I(2,col)];
c3 = state[I(3,col)];
// do inverse mixing, and put back into array
state[I(0,col)] = aes_mul(0x0e,c0) ^ aes_mul(0x0b,c1)
^ aes_mul(0x0d,c2) ^ aes_mul(0x09,c3);
state[I(1,col)] = aes_mul(0x09,c0) ^ aes_mul(0x0e,c1)
^ aes_mul(0x0b,c2) ^ aes_mul(0x0d,c3);
state[I(2,col)] = aes_mul(0x0d,c0) ^ aes_mul(0x09,c1)
^ aes_mul(0x0e,c2) ^ aes_mul(0x0b,c3);
state[I(3,col)] = aes_mul(0x0b,c0) ^ aes_mul(0x0d,c1)
^ aes_mul(0x09,c2) ^ aes_mul(0x0e,c3);
}
return state;
}
// insert subkey information
function AddRoundKey( state, w, base )
{
var col;
for( col=0; col<4; col++ )
{
state[I(0,col)] ^= w[base+col*4];
state[I(1,col)] ^= w[base+col*4+1];
state[I(2,col)] ^= w[base+col*4+2];
state[I(3,col)] ^= w[base+col*4+3];
}
return state;
}
// return a transposed array
function transpose( msg )
{
var row, col;
var state = new Array( 16 );
for( row=0; row<4; row++ )
for( col=0; col<4; col++ )
state[I(row,col)] = msg[I(col,row)];
return state;
}
// final AES state
var AES_output = new Array(16);
// format AES output
// -- uses the global array DES_output
function format_AES_output(bASCII)
{
var i;
var bits;
var str="";
// what type of data do we have to work with?
if (bASCII)
{
// convert each set of bits back to ASCII
for( i=0; i<16; i++ )
str += String.fromCharCode( AES_output[i] );
}
else
{
// output hexdecimal data (insert spaces)
str = cvt_hex8( AES_output[0] );
for( i=1; i<16; i++ )
{
str += "" + cvt_hex8( AES_output[i] );
}
}
return str;
}
// do encrytion
function aes_encrypt(str, key, bASCII)
{
//console.log(" aes_encrypt:\tstr = " + str + "\tkey = " + key + "\t bASCII = " + bASCII);
var w = new Array( 4*(Nr+1) ); // subkey information
var state = new Array( 16 ); // working state
var round;
//accumulated_output_info = "";
// get the message from the user
// also check if it is ASCII or hex
var msg = get_value(str, bASCII);
// problems??
if ( msg[0] < 0 )
{
return;
}
// get the key from the user
var key = get_value(key, false);
// problems??
if ( key[0] < 0 )
{
return;
}
// expand the key
w = key_expand( key );
// initial state = message in columns (transposed from what we input)
state = transpose( msg );
// display the round key - Transpose due to the way it is stored/used
state = AddRoundKey(state, w, 0);
for( round=1; round<Nr; round++ )
{
state = SubBytes(state, S_enc);
state = ShiftRows(state);
state = MixColumns(state);
// display the round key - Transpose due to the way it is stored/used
// note here the spec uses 32-bit words, we are using bytes, so an extra *4
state = AddRoundKey(state, w, round*4*4);
}
SubBytes(state, S_enc);
ShiftRows(state);
AddRoundKey(state, w, Nr*4*4);
// process output
AES_output = transpose( state );
var szOutput = format_AES_output(!bASCII);
return szOutput;
}
// do decryption
function aes_decrypt(str, key, bASCII)
{
//console.log(" aes_decrypt:\tstr = " + str + "\tkey = " + key + "\tbASCII = " + bASCII);
var w = new Array( 4*(Nr+1) ); // subkey information
var state = new Array( 16 ); // working state
var round;
//accumulated_output_info = "";
// get the message from the user
// also check if it is ASCII or hex
var msg = get_value(str, bASCII);
// problems??
if ( msg[0] < 0 )
{
return;
}
// get the key from the user
var key = get_value(key, false);
// problems??
if ( key[0] < 0 )
{
return;
}
// expand the key
w = key_expand( key );
// initial state = message
state = transpose( msg );
// display the round key - Transpose due to the way it is stored/used
state = AddRoundKey(state, w, Nr*4*4);
for( round=Nr-1; round>=1; round-- )
{
state = InvShiftRows(state);
state = SubBytes(state, S_dec);
// display the round key - Transpose due to the way it is stored/used
// note here the spec uses 32-bit words, we are using bytes, so an extra *4
state = AddRoundKey(state, w, round*4*4);
state = InvMixColumns(state);
}
InvShiftRows(state);
SubBytes(state, S_dec);
AddRoundKey(state, w, 0);
// process output
AES_output = transpose( state );
var szOutput = format_AES_output(!bASCII);
return szOutput;
}
window.aes_encrypt = aes_encrypt;
window.aes_decrypt = aes_decrypt;
window.console = window.console || {
log: function() {}
};
}());
\ No newline at end of file
var dbits,canary=244837814094590,j_lm=(canary&16777215)==15715070;function BigInteger(a,b,c){a!=null&&("number"==typeof a?this.fromNumber(a,b,c):b==null&&"string"!=typeof a?this.fromString(a,256):this.fromString(a,b))}function nbi(){return new BigInteger(null)}function am1(a,b,c,d,e,g){for(;--g>=0;){var h=b*this[a++]+c[d]+e,e=Math.floor(h/67108864);c[d++]=h&67108863}return e}
function am2(a,b,c,d,e,g){var h=b&32767;for(b>>=15;--g>=0;){var f=this[a]&32767,o=this[a++]>>15,p=b*f+o*h,f=h*f+((p&32767)<<15)+c[d]+(e&1073741823),e=(f>>>30)+(p>>>15)+b*o+(e>>>30);c[d++]=f&1073741823}return e}function am3(a,b,c,d,e,g){var h=b&16383;for(b>>=14;--g>=0;){var f=this[a]&16383,o=this[a++]>>14,p=b*f+o*h,f=h*f+((p&16383)<<14)+c[d]+e,e=(f>>28)+(p>>14)+b*o;c[d++]=f&268435455}return e}
j_lm&&navigator.appName=="Microsoft Internet Explorer"?(BigInteger.prototype.am=am2,dbits=30):j_lm&&navigator.appName!="Netscape"?(BigInteger.prototype.am=am1,dbits=26):(BigInteger.prototype.am=am3,dbits=28);BigInteger.prototype.DB=dbits;BigInteger.prototype.DM=(1<<dbits)-1;BigInteger.prototype.DV=1<<dbits;var BI_FP=52;BigInteger.prototype.FV=Math.pow(2,BI_FP);BigInteger.prototype.F1=BI_FP-dbits;BigInteger.prototype.F2=2*dbits-BI_FP;var BI_RM="0123456789abcdefghijklmnopqrstuvwxyz",BI_RC=[],rr,vv;
rr="0".charCodeAt(0);for(vv=0;vv<=9;++vv)BI_RC[rr++]=vv;rr="a".charCodeAt(0);for(vv=10;vv<36;++vv)BI_RC[rr++]=vv;rr="A".charCodeAt(0);for(vv=10;vv<36;++vv)BI_RC[rr++]=vv;function int2char(a){return BI_RM.charAt(a)}function intAt(a,b){var c=BI_RC[a.charCodeAt(b)];return c==null?-1:c}function bnpCopyTo(a){for(var b=this.t-1;b>=0;--b)a[b]=this[b];a.t=this.t;a.s=this.s}function bnpFromInt(a){this.t=1;this.s=a<0?-1:0;a>0?this[0]=a:a<-1?this[0]=a+DV:this.t=0}
function nbv(a){var b=nbi();b.fromInt(a);return b}
function bnpFromString(a,b){var c;if(b==16)c=4;else if(b==8)c=3;else if(b==256)c=8;else if(b==2)c=1;else if(b==32)c=5;else if(b==4)c=2;else{this.fromRadix(a,b);return}this.s=this.t=0;for(var d=a.length,e=!1,g=0;--d>=0;){var h=c==8?a[d]&255:intAt(a,d);h<0?a.charAt(d)=="-"&&(e=!0):(e=!1,g==0?this[this.t++]=h:g+c>this.DB?(this[this.t-1]|=(h&(1<<this.DB-g)-1)<<g,this[this.t++]=h>>this.DB-g):this[this.t-1]|=h<<g,g+=c,g>=this.DB&&(g-=this.DB))}if(c==8&&(a[0]&128)!=0)this.s=-1,g>0&&(this[this.t-1]|=(1<<
this.DB-g)-1<<g);this.clamp();e&&BigInteger.ZERO.subTo(this,this)}function bnpClamp(){for(var a=this.s&this.DM;this.t>0&&this[this.t-1]==a;)--this.t}
function bnToString(a){if(this.s<0)return"-"+this.negate().toString(a);if(a==16)a=4;else if(a==8)a=3;else if(a==2)a=1;else if(a==32)a=5;else if(a==64)a=6;else if(a==4)a=2;else return this.toRadix(a);var b=(1<<a)-1,c,d=!1,e="",g=this.t,h=this.DB-g*this.DB%a;if(g-- >0){if(h<this.DB&&(c=this[g]>>h)>0)d=!0,e=int2char(c);for(;g>=0;)h<a?(c=(this[g]&(1<<h)-1)<<a-h,c|=this[--g]>>(h+=this.DB-a)):(c=this[g]>>(h-=a)&b,h<=0&&(h+=this.DB,--g)),c>0&&(d=!0),d&&(e+=int2char(c))}return d?e:"0"}
function bnNegate(){var a=nbi();BigInteger.ZERO.subTo(this,a);return a}function bnAbs(){return this.s<0?this.negate():this}function bnCompareTo(a){var b=this.s-a.s;if(b!=0)return b;var c=this.t,b=c-a.t;if(b!=0)return b;for(;--c>=0;)if((b=this[c]-a[c])!=0)return b;return 0}function nbits(a){var b=1,c;if((c=a>>>16)!=0)a=c,b+=16;if((c=a>>8)!=0)a=c,b+=8;if((c=a>>4)!=0)a=c,b+=4;if((c=a>>2)!=0)a=c,b+=2;a>>1!=0&&(b+=1);return b}
function bnBitLength(){return this.t<=0?0:this.DB*(this.t-1)+nbits(this[this.t-1]^this.s&this.DM)}function bnpDLShiftTo(a,b){var c;for(c=this.t-1;c>=0;--c)b[c+a]=this[c];for(c=a-1;c>=0;--c)b[c]=0;b.t=this.t+a;b.s=this.s}function bnpDRShiftTo(a,b){for(var c=a;c<this.t;++c)b[c-a]=this[c];b.t=Math.max(this.t-a,0);b.s=this.s}
function bnpLShiftTo(a,b){var c=a%this.DB,d=this.DB-c,e=(1<<d)-1,g=Math.floor(a/this.DB),h=this.s<<c&this.DM,f;for(f=this.t-1;f>=0;--f)b[f+g+1]=this[f]>>d|h,h=(this[f]&e)<<c;for(f=g-1;f>=0;--f)b[f]=0;b[g]=h;b.t=this.t+g+1;b.s=this.s;b.clamp()}
function bnpRShiftTo(a,b){b.s=this.s;var c=Math.floor(a/this.DB);if(c>=this.t)b.t=0;else{var d=a%this.DB,e=this.DB-d,g=(1<<d)-1;b[0]=this[c]>>d;for(var h=c+1;h<this.t;++h)b[h-c-1]|=(this[h]&g)<<e,b[h-c]=this[h]>>d;d>0&&(b[this.t-c-1]|=(this.s&g)<<e);b.t=this.t-c;b.clamp()}}
function bnpSubTo(a,b){for(var c=0,d=0,e=Math.min(a.t,this.t);c<e;)d+=this[c]-a[c],b[c++]=d&this.DM,d>>=this.DB;if(a.t<this.t){for(d-=a.s;c<this.t;)d+=this[c],b[c++]=d&this.DM,d>>=this.DB;d+=this.s}else{for(d+=this.s;c<a.t;)d-=a[c],b[c++]=d&this.DM,d>>=this.DB;d-=a.s}b.s=d<0?-1:0;d<-1?b[c++]=this.DV+d:d>0&&(b[c++]=d);b.t=c;b.clamp()}
function bnpMultiplyTo(a,b){var c=this.abs(),d=a.abs(),e=c.t;for(b.t=e+d.t;--e>=0;)b[e]=0;for(e=0;e<d.t;++e)b[e+c.t]=c.am(0,d[e],b,e,0,c.t);b.s=0;b.clamp();this.s!=a.s&&BigInteger.ZERO.subTo(b,b)}function bnpSquareTo(a){for(var b=this.abs(),c=a.t=2*b.t;--c>=0;)a[c]=0;for(c=0;c<b.t-1;++c){var d=b.am(c,b[c],a,2*c,0,1);if((a[c+b.t]+=b.am(c+1,2*b[c],a,2*c+1,d,b.t-c-1))>=b.DV)a[c+b.t]-=b.DV,a[c+b.t+1]=1}a.t>0&&(a[a.t-1]+=b.am(c,b[c],a,2*c,0,1));a.s=0;a.clamp()}
function bnpDivRemTo(a,b,c){var d=a.abs();if(!(d.t<=0)){var e=this.abs();if(e.t<d.t)b!=null&&b.fromInt(0),c!=null&&this.copyTo(c);else{c==null&&(c=nbi());var g=nbi(),h=this.s,a=a.s,f=this.DB-nbits(d[d.t-1]);f>0?(d.lShiftTo(f,g),e.lShiftTo(f,c)):(d.copyTo(g),e.copyTo(c));d=g.t;e=g[d-1];if(e!=0){var o=e*(1<<this.F1)+(d>1?g[d-2]>>this.F2:0),p=this.FV/o,o=(1<<this.F1)/o,q=1<<this.F2,n=c.t,k=n-d,j=b==null?nbi():b;g.dlShiftTo(k,j);c.compareTo(j)>=0&&(c[c.t++]=1,c.subTo(j,c));BigInteger.ONE.dlShiftTo(d,
j);for(j.subTo(g,g);g.t<d;)g[g.t++]=0;for(;--k>=0;){var l=c[--n]==e?this.DM:Math.floor(c[n]*p+(c[n-1]+q)*o);if((c[n]+=g.am(0,l,c,k,0,d))<l){g.dlShiftTo(k,j);for(c.subTo(j,c);c[n]<--l;)c.subTo(j,c)}}b!=null&&(c.drShiftTo(d,b),h!=a&&BigInteger.ZERO.subTo(b,b));c.t=d;c.clamp();f>0&&c.rShiftTo(f,c);h<0&&BigInteger.ZERO.subTo(c,c)}}}}function bnMod(a){var b=nbi();this.abs().divRemTo(a,null,b);this.s<0&&b.compareTo(BigInteger.ZERO)>0&&a.subTo(b,b);return b}function Classic(a){this.m=a}
function cConvert(a){return a.s<0||a.compareTo(this.m)>=0?a.mod(this.m):a}function cRevert(a){return a}function cReduce(a){a.divRemTo(this.m,null,a)}function cMulTo(a,b,c){a.multiplyTo(b,c);this.reduce(c)}function cSqrTo(a,b){a.squareTo(b);this.reduce(b)}Classic.prototype.convert=cConvert;Classic.prototype.revert=cRevert;Classic.prototype.reduce=cReduce;Classic.prototype.mulTo=cMulTo;Classic.prototype.sqrTo=cSqrTo;
function bnpInvDigit(){if(this.t<1)return 0;var a=this[0];if((a&1)==0)return 0;var b=a&3,b=b*(2-(a&15)*b)&15,b=b*(2-(a&255)*b)&255,b=b*(2-((a&65535)*b&65535))&65535,b=b*(2-a*b%this.DV)%this.DV;return b>0?this.DV-b:-b}function Montgomery(a){this.m=a;this.mp=a.invDigit();this.mpl=this.mp&32767;this.mph=this.mp>>15;this.um=(1<<a.DB-15)-1;this.mt2=2*a.t}
function montConvert(a){var b=nbi();a.abs().dlShiftTo(this.m.t,b);b.divRemTo(this.m,null,b);a.s<0&&b.compareTo(BigInteger.ZERO)>0&&this.m.subTo(b,b);return b}function montRevert(a){var b=nbi();a.copyTo(b);this.reduce(b);return b}
function montReduce(a){for(;a.t<=this.mt2;)a[a.t++]=0;for(var b=0;b<this.m.t;++b){var c=a[b]&32767,d=c*this.mpl+((c*this.mph+(a[b]>>15)*this.mpl&this.um)<<15)&a.DM,c=b+this.m.t;for(a[c]+=this.m.am(0,d,a,b,0,this.m.t);a[c]>=a.DV;)a[c]-=a.DV,a[++c]++}a.clamp();a.drShiftTo(this.m.t,a);a.compareTo(this.m)>=0&&a.subTo(this.m,a)}function montSqrTo(a,b){a.squareTo(b);this.reduce(b)}function montMulTo(a,b,c){a.multiplyTo(b,c);this.reduce(c)}Montgomery.prototype.convert=montConvert;
Montgomery.prototype.revert=montRevert;Montgomery.prototype.reduce=montReduce;Montgomery.prototype.mulTo=montMulTo;Montgomery.prototype.sqrTo=montSqrTo;function bnpIsEven(){return(this.t>0?this[0]&1:this.s)==0}function bnpExp(a,b){if(a>4294967295||a<1)return BigInteger.ONE;var c=nbi(),d=nbi(),e=b.convert(this),g=nbits(a)-1;for(e.copyTo(c);--g>=0;)if(b.sqrTo(c,d),(a&1<<g)>0)b.mulTo(d,e,c);else var h=c,c=d,d=h;return b.revert(c)}
function bnModPowInt(a,b){var c;c=a<256||b.isEven()?new Classic(b):new Montgomery(b);return this.exp(a,c)}BigInteger.prototype.copyTo=bnpCopyTo;BigInteger.prototype.fromInt=bnpFromInt;BigInteger.prototype.fromString=bnpFromString;BigInteger.prototype.clamp=bnpClamp;BigInteger.prototype.dlShiftTo=bnpDLShiftTo;BigInteger.prototype.drShiftTo=bnpDRShiftTo;BigInteger.prototype.lShiftTo=bnpLShiftTo;BigInteger.prototype.rShiftTo=bnpRShiftTo;BigInteger.prototype.subTo=bnpSubTo;
BigInteger.prototype.multiplyTo=bnpMultiplyTo;BigInteger.prototype.squareTo=bnpSquareTo;BigInteger.prototype.divRemTo=bnpDivRemTo;BigInteger.prototype.invDigit=bnpInvDigit;BigInteger.prototype.isEven=bnpIsEven;BigInteger.prototype.exp=bnpExp;BigInteger.prototype.toString=bnToString;BigInteger.prototype.negate=bnNegate;BigInteger.prototype.abs=bnAbs;BigInteger.prototype.compareTo=bnCompareTo;BigInteger.prototype.bitLength=bnBitLength;BigInteger.prototype.mod=bnMod;BigInteger.prototype.modPowInt=bnModPowInt;
BigInteger.ZERO=nbv(0);BigInteger.ONE=nbv(1);function bnClone(){var a=nbi();this.copyTo(a);return a}function bnIntValue(){if(this.s<0)if(this.t==1)return this[0]-this.DV;else{if(this.t==0)return-1}else if(this.t==1)return this[0];else if(this.t==0)return 0;return(this[1]&(1<<32-this.DB)-1)<<this.DB|this[0]}function bnByteValue(){return this.t==0?this.s:this[0]<<24>>24}function bnShortValue(){return this.t==0?this.s:this[0]<<16>>16}
function bnpChunkSize(a){return Math.floor(Math.LN2*this.DB/Math.log(a))}function bnSigNum(){return this.s<0?-1:this.t<=0||this.t==1&&this[0]<=0?0:1}function bnpToRadix(a){a==null&&(a=10);if(this.signum()==0||a<2||a>36)return"0";var b=this.chunkSize(a),b=Math.pow(a,b),c=nbv(b),d=nbi(),e=nbi(),g="";for(this.divRemTo(c,d,e);d.signum()>0;)g=(b+e.intValue()).toString(a).substr(1)+g,d.divRemTo(c,d,e);return e.intValue().toString(a)+g}
function bnpFromRadix(a,b){this.fromInt(0);b==null&&(b=10);for(var c=this.chunkSize(b),d=Math.pow(b,c),e=!1,g=0,h=0,f=0;f<a.length;++f){var o=intAt(a,f);o<0?a.charAt(f)=="-"&&this.signum()==0&&(e=!0):(h=b*h+o,++g>=c&&(this.dMultiply(d),this.dAddOffset(h,0),h=g=0))}g>0&&(this.dMultiply(Math.pow(b,g)),this.dAddOffset(h,0));e&&BigInteger.ZERO.subTo(this,this)}
function bnpFromNumber(a,b,c){if("number"==typeof b)if(a<2)this.fromInt(1);else{this.fromNumber(a,c);this.testBit(a-1)||this.bitwiseTo(BigInteger.ONE.shiftLeft(a-1),op_or,this);for(this.isEven()&&this.dAddOffset(1,0);!this.isProbablePrime(b);)this.dAddOffset(2,0),this.bitLength()>a&&this.subTo(BigInteger.ONE.shiftLeft(a-1),this)}else{var c=[],d=a&7;c.length=(a>>3)+1;b.nextBytes(c);d>0?c[0]&=(1<<d)-1:c[0]=0;this.fromString(c,256)}}
function bnToByteArray(){var a=this.t,b=[];b[0]=this.s;var c=this.DB-a*this.DB%8,d,e=0;if(a-- >0){if(c<this.DB&&(d=this[a]>>c)!=(this.s&this.DM)>>c)b[e++]=d|this.s<<this.DB-c;for(;a>=0;)if(c<8?(d=(this[a]&(1<<c)-1)<<8-c,d|=this[--a]>>(c+=this.DB-8)):(d=this[a]>>(c-=8)&255,c<=0&&(c+=this.DB,--a)),(d&128)!=0&&(d|=-256),e==0&&(this.s&128)!=(d&128)&&++e,e>0||d!=this.s)b[e++]=d}return b}function bnEquals(a){return this.compareTo(a)==0}function bnMin(a){return this.compareTo(a)<0?this:a}
function bnMax(a){return this.compareTo(a)>0?this:a}function bnpBitwiseTo(a,b,c){var d,e,g=Math.min(a.t,this.t);for(d=0;d<g;++d)c[d]=b(this[d],a[d]);if(a.t<this.t){e=a.s&this.DM;for(d=g;d<this.t;++d)c[d]=b(this[d],e);c.t=this.t}else{e=this.s&this.DM;for(d=g;d<a.t;++d)c[d]=b(e,a[d]);c.t=a.t}c.s=b(this.s,a.s);c.clamp()}function op_and(a,b){return a&b}function bnAnd(a){var b=nbi();this.bitwiseTo(a,op_and,b);return b}function op_or(a,b){return a|b}
function bnOr(a){var b=nbi();this.bitwiseTo(a,op_or,b);return b}function op_xor(a,b){return a^b}function bnXor(a){var b=nbi();this.bitwiseTo(a,op_xor,b);return b}function op_andnot(a,b){return a&~b}function bnAndNot(a){var b=nbi();this.bitwiseTo(a,op_andnot,b);return b}function bnNot(){for(var a=nbi(),b=0;b<this.t;++b)a[b]=this.DM&~this[b];a.t=this.t;a.s=~this.s;return a}function bnShiftLeft(a){var b=nbi();a<0?this.rShiftTo(-a,b):this.lShiftTo(a,b);return b}
function bnShiftRight(a){var b=nbi();a<0?this.lShiftTo(-a,b):this.rShiftTo(a,b);return b}function lbit(a){if(a==0)return-1;var b=0;(a&65535)==0&&(a>>=16,b+=16);(a&255)==0&&(a>>=8,b+=8);(a&15)==0&&(a>>=4,b+=4);(a&3)==0&&(a>>=2,b+=2);(a&1)==0&&++b;return b}function bnGetLowestSetBit(){for(var a=0;a<this.t;++a)if(this[a]!=0)return a*this.DB+lbit(this[a]);return this.s<0?this.t*this.DB:-1}function cbit(a){for(var b=0;a!=0;)a&=a-1,++b;return b}
function bnBitCount(){for(var a=0,b=this.s&this.DM,c=0;c<this.t;++c)a+=cbit(this[c]^b);return a}function bnTestBit(a){var b=Math.floor(a/this.DB);return b>=this.t?this.s!=0:(this[b]&1<<a%this.DB)!=0}function bnpChangeBit(a,b){var c=BigInteger.ONE.shiftLeft(a);this.bitwiseTo(c,b,c);return c}function bnSetBit(a){return this.changeBit(a,op_or)}function bnClearBit(a){return this.changeBit(a,op_andnot)}function bnFlipBit(a){return this.changeBit(a,op_xor)}
function bnpAddTo(a,b){for(var c=0,d=0,e=Math.min(a.t,this.t);c<e;)d+=this[c]+a[c],b[c++]=d&this.DM,d>>=this.DB;if(a.t<this.t){for(d+=a.s;c<this.t;)d+=this[c],b[c++]=d&this.DM,d>>=this.DB;d+=this.s}else{for(d+=this.s;c<a.t;)d+=a[c],b[c++]=d&this.DM,d>>=this.DB;d+=a.s}b.s=d<0?-1:0;d>0?b[c++]=d:d<-1&&(b[c++]=this.DV+d);b.t=c;b.clamp()}function bnAdd(a){var b=nbi();this.addTo(a,b);return b}function bnSubtract(a){var b=nbi();this.subTo(a,b);return b}
function bnMultiply(a){var b=nbi();this.multiplyTo(a,b);return b}function bnSquare(){var a=nbi();this.squareTo(a);return a}function bnDivide(a){var b=nbi();this.divRemTo(a,b,null);return b}function bnRemainder(a){var b=nbi();this.divRemTo(a,null,b);return b}function bnDivideAndRemainder(a){var b=nbi(),c=nbi();this.divRemTo(a,b,c);return[b,c]}function bnpDMultiply(a){this[this.t]=this.am(0,a-1,this,0,0,this.t);++this.t;this.clamp()}
function bnpDAddOffset(a,b){if(a!=0){for(;this.t<=b;)this[this.t++]=0;for(this[b]+=a;this[b]>=this.DV;)this[b]-=this.DV,++b>=this.t&&(this[this.t++]=0),++this[b]}}function NullExp(){}function nNop(a){return a}function nMulTo(a,b,c){a.multiplyTo(b,c)}function nSqrTo(a,b){a.squareTo(b)}NullExp.prototype.convert=nNop;NullExp.prototype.revert=nNop;NullExp.prototype.mulTo=nMulTo;NullExp.prototype.sqrTo=nSqrTo;function bnPow(a){return this.exp(a,new NullExp)}
function bnpMultiplyLowerTo(a,b,c){var d=Math.min(this.t+a.t,b);c.s=0;for(c.t=d;d>0;)c[--d]=0;var e;for(e=c.t-this.t;d<e;++d)c[d+this.t]=this.am(0,a[d],c,d,0,this.t);for(e=Math.min(a.t,b);d<e;++d)this.am(0,a[d],c,d,0,b-d);c.clamp()}function bnpMultiplyUpperTo(a,b,c){--b;var d=c.t=this.t+a.t-b;for(c.s=0;--d>=0;)c[d]=0;for(d=Math.max(b-this.t,0);d<a.t;++d)c[this.t+d-b]=this.am(b-d,a[d],c,0,0,this.t+d-b);c.clamp();c.drShiftTo(1,c)}
function Barrett(a){this.r2=nbi();this.q3=nbi();BigInteger.ONE.dlShiftTo(2*a.t,this.r2);this.mu=this.r2.divide(a);this.m=a}function barrettConvert(a){if(a.s<0||a.t>2*this.m.t)return a.mod(this.m);else if(a.compareTo(this.m)<0)return a;else{var b=nbi();a.copyTo(b);this.reduce(b);return b}}function barrettRevert(a){return a}
function barrettReduce(a){a.drShiftTo(this.m.t-1,this.r2);if(a.t>this.m.t+1)a.t=this.m.t+1,a.clamp();this.mu.multiplyUpperTo(this.r2,this.m.t+1,this.q3);for(this.m.multiplyLowerTo(this.q3,this.m.t+1,this.r2);a.compareTo(this.r2)<0;)a.dAddOffset(1,this.m.t+1);for(a.subTo(this.r2,a);a.compareTo(this.m)>=0;)a.subTo(this.m,a)}function barrettSqrTo(a,b){a.squareTo(b);this.reduce(b)}function barrettMulTo(a,b,c){a.multiplyTo(b,c);this.reduce(c)}Barrett.prototype.convert=barrettConvert;
Barrett.prototype.revert=barrettRevert;Barrett.prototype.reduce=barrettReduce;Barrett.prototype.mulTo=barrettMulTo;Barrett.prototype.sqrTo=barrettSqrTo;
function bnModPow(a,b){var c=a.bitLength(),d,e=nbv(1),g;if(c<=0)return e;else d=c<18?1:c<48?3:c<144?4:c<768?5:6;g=c<8?new Classic(b):b.isEven()?new Barrett(b):new Montgomery(b);var h=[],f=3,o=d-1,p=(1<<d)-1;h[1]=g.convert(this);if(d>1){c=nbi();for(g.sqrTo(h[1],c);f<=p;)h[f]=nbi(),g.mulTo(c,h[f-2],h[f]),f+=2}for(var q=a.t-1,n,k=!0,j=nbi(),c=nbits(a[q])-1;q>=0;){c>=o?n=a[q]>>c-o&p:(n=(a[q]&(1<<c+1)-1)<<o-c,q>0&&(n|=a[q-1]>>this.DB+c-o));for(f=d;(n&1)==0;)n>>=1,--f;if((c-=f)<0)c+=this.DB,--q;if(k)h[n].copyTo(e),
k=!1;else{for(;f>1;)g.sqrTo(e,j),g.sqrTo(j,e),f-=2;f>0?g.sqrTo(e,j):(f=e,e=j,j=f);g.mulTo(j,h[n],e)}for(;q>=0&&(a[q]&1<<c)==0;)g.sqrTo(e,j),f=e,e=j,j=f,--c<0&&(c=this.DB-1,--q)}return g.revert(e)}
function bnGCD(a){var b=this.s<0?this.negate():this.clone(),a=a.s<0?a.negate():a.clone();if(b.compareTo(a)<0)var c=b,b=a,a=c;var c=b.getLowestSetBit(),d=a.getLowestSetBit();if(d<0)return b;c<d&&(d=c);d>0&&(b.rShiftTo(d,b),a.rShiftTo(d,a));for(;b.signum()>0;)(c=b.getLowestSetBit())>0&&b.rShiftTo(c,b),(c=a.getLowestSetBit())>0&&a.rShiftTo(c,a),b.compareTo(a)>=0?(b.subTo(a,b),b.rShiftTo(1,b)):(a.subTo(b,a),a.rShiftTo(1,a));d>0&&a.lShiftTo(d,a);return a}
function bnpModInt(a){if(a<=0)return 0;var b=this.DV%a,c=this.s<0?a-1:0;if(this.t>0)if(b==0)c=this[0]%a;else for(var d=this.t-1;d>=0;--d)c=(b*c+this[d])%a;return c}
function bnModInverse(a){var b=a.isEven();if(this.isEven()&&b||a.signum()==0)return BigInteger.ZERO;for(var c=a.clone(),d=this.clone(),e=nbv(1),g=nbv(0),h=nbv(0),f=nbv(1);c.signum()!=0;){for(;c.isEven();){c.rShiftTo(1,c);if(b){if(!e.isEven()||!g.isEven())e.addTo(this,e),g.subTo(a,g);e.rShiftTo(1,e)}else g.isEven()||g.subTo(a,g);g.rShiftTo(1,g)}for(;d.isEven();){d.rShiftTo(1,d);if(b){if(!h.isEven()||!f.isEven())h.addTo(this,h),f.subTo(a,f);h.rShiftTo(1,h)}else f.isEven()||f.subTo(a,f);f.rShiftTo(1,
f)}c.compareTo(d)>=0?(c.subTo(d,c),b&&e.subTo(h,e),g.subTo(f,g)):(d.subTo(c,d),b&&h.subTo(e,h),f.subTo(g,f))}if(d.compareTo(BigInteger.ONE)!=0)return BigInteger.ZERO;if(f.compareTo(a)>=0)return f.subtract(a);if(f.signum()<0)f.addTo(a,f);else return f;return f.signum()<0?f.add(a):f}
var lowprimes=[2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509,521,523,541,547,557,563,569,571,577,587,593,599,601,607,613,617,619,631,641,643,647,653,659,661,673,677,683,691,701,709,719,727,
733,739,743,751,757,761,769,773,787,797,809,811,821,823,827,829,839,853,857,859,863,877,881,883,887,907,911,919,929,937,941,947,953,967,971,977,983,991,997],lplim=67108864/lowprimes[lowprimes.length-1];
function bnIsProbablePrime(a){var b,c=this.abs();if(c.t==1&&c[0]<=lowprimes[lowprimes.length-1]){for(b=0;b<lowprimes.length;++b)if(c[0]==lowprimes[b])return!0;return!1}if(c.isEven())return!1;for(b=1;b<lowprimes.length;){for(var d=lowprimes[b],e=b+1;e<lowprimes.length&&d<lplim;)d*=lowprimes[e++];for(d=c.modInt(d);b<e;)if(d%lowprimes[b++]==0)return!1}return c.millerRabin(a)}
function bnpMillerRabin(a){var b=this.subtract(BigInteger.ONE),c=b.getLowestSetBit();if(c<=0)return!1;var d=b.shiftRight(c),a=a+1>>1;if(a>lowprimes.length)a=lowprimes.length;for(var e=nbi(),g=0;g<a;++g){e.fromInt(lowprimes[Math.floor(Math.random()*lowprimes.length)]);var h=e.modPow(d,this);if(h.compareTo(BigInteger.ONE)!=0&&h.compareTo(b)!=0){for(var f=1;f++<c&&h.compareTo(b)!=0;)if(h=h.modPowInt(2,this),h.compareTo(BigInteger.ONE)==0)return!1;if(h.compareTo(b)!=0)return!1}}return!0}
BigInteger.prototype.chunkSize=bnpChunkSize;BigInteger.prototype.toRadix=bnpToRadix;BigInteger.prototype.fromRadix=bnpFromRadix;BigInteger.prototype.fromNumber=bnpFromNumber;BigInteger.prototype.bitwiseTo=bnpBitwiseTo;BigInteger.prototype.changeBit=bnpChangeBit;BigInteger.prototype.addTo=bnpAddTo;BigInteger.prototype.dMultiply=bnpDMultiply;BigInteger.prototype.dAddOffset=bnpDAddOffset;BigInteger.prototype.multiplyLowerTo=bnpMultiplyLowerTo;BigInteger.prototype.multiplyUpperTo=bnpMultiplyUpperTo;
BigInteger.prototype.modInt=bnpModInt;BigInteger.prototype.millerRabin=bnpMillerRabin;BigInteger.prototype.clone=bnClone;BigInteger.prototype.intValue=bnIntValue;BigInteger.prototype.byteValue=bnByteValue;BigInteger.prototype.shortValue=bnShortValue;BigInteger.prototype.signum=bnSigNum;BigInteger.prototype.toByteArray=bnToByteArray;BigInteger.prototype.equals=bnEquals;BigInteger.prototype.min=bnMin;BigInteger.prototype.max=bnMax;BigInteger.prototype.and=bnAnd;BigInteger.prototype.or=bnOr;
BigInteger.prototype.xor=bnXor;BigInteger.prototype.andNot=bnAndNot;BigInteger.prototype.not=bnNot;BigInteger.prototype.shiftLeft=bnShiftLeft;BigInteger.prototype.shiftRight=bnShiftRight;BigInteger.prototype.getLowestSetBit=bnGetLowestSetBit;BigInteger.prototype.bitCount=bnBitCount;BigInteger.prototype.testBit=bnTestBit;BigInteger.prototype.setBit=bnSetBit;BigInteger.prototype.clearBit=bnClearBit;BigInteger.prototype.flipBit=bnFlipBit;BigInteger.prototype.add=bnAdd;BigInteger.prototype.subtract=bnSubtract;
BigInteger.prototype.multiply=bnMultiply;BigInteger.prototype.divide=bnDivide;BigInteger.prototype.remainder=bnRemainder;BigInteger.prototype.divideAndRemainder=bnDivideAndRemainder;BigInteger.prototype.modPow=bnModPow;BigInteger.prototype.modInverse=bnModInverse;BigInteger.prototype.pow=bnPow;BigInteger.prototype.gcd=bnGCD;BigInteger.prototype.isProbablePrime=bnIsProbablePrime;BigInteger.prototype.square=bnSquare;
(function(a,b,c,d,e,g,h){function f(a){var b,d,e=this,g=a.length,f=0,h=e.i=e.j=e.m=0;e.S=[];e.c=[];for(g||(a=[g++]);f<c;)e.S[f]=f++;for(f=0;f<c;f++)b=e.S[f],h=h+b+a[f%g]&c-1,d=e.S[h],e.S[f]=d,e.S[h]=b;e.g=function(a){var b=e.S,d=e.i+1&c-1,g=b[d],f=e.j+g&c-1,h=b[f];b[d]=h;b[f]=g;for(var k=b[g+h&c-1];--a;)d=d+1&c-1,g=b[d],f=f+g&c-1,h=b[f],b[d]=h,b[f]=g,k=k*c+b[g+h&c-1];e.i=d;e.j=f;return k};e.g(c)}function o(a,b,c,d,e){c=[];e=typeof a;if(b&&e=="object")for(d in a)if(d.indexOf("S")<5)try{c.push(o(a[d],
b-1))}catch(g){}return c.length?c:a+(e!="string"?"\x00":"")}function p(a,b,d,e){a+="";for(e=d=0;e<a.length;e++){var g=b,f=e&c-1,h=(d^=b[e&c-1]*19)+a.charCodeAt(e);g[f]=h&c-1}a="";for(e in b)a+=String.fromCharCode(b[e]);return a}b.seedrandom=function(q,n){var k=[],j,q=p(o(n?[q,a]:arguments.length?q:[(new Date).getTime(),a,window],3),k);j=new f(k);p(j.S,a);b.random=function(){for(var a=j.g(d),b=h,f=0;a<e;)a=(a+f)*c,b*=c,f=j.g(1);for(;a>=g;)a/=2,b/=2,f>>>=1;return(a+f)/b};return q};h=b.pow(c,d);e=b.pow(2,
e);g=e*2;p(b.random(),a)})([],Math,256,6,52);function SeededRandom(){}function SRnextBytes(a){var b;for(b=0;b<a.length;b++)a[b]=Math.floor(Math.random()*256)}SeededRandom.prototype.nextBytes=SRnextBytes;function Arcfour(){this.j=this.i=0;this.S=[]}function ARC4init(a){var b,c,d;for(b=0;b<256;++b)this.S[b]=b;for(b=c=0;b<256;++b)c=c+this.S[b]+a[b%a.length]&255,d=this.S[b],this.S[b]=this.S[c],this.S[c]=d;this.j=this.i=0}
function ARC4next(){var a;this.i=this.i+1&255;this.j=this.j+this.S[this.i]&255;a=this.S[this.i];this.S[this.i]=this.S[this.j];this.S[this.j]=a;return this.S[a+this.S[this.i]&255]}Arcfour.prototype.init=ARC4init;Arcfour.prototype.next=ARC4next;function prng_newstate(){return new Arcfour}var rng_psize=256,rng_state,rng_pool,rng_pptr;
function rng_seed_int(a){rng_pool[rng_pptr++]^=a&255;rng_pool[rng_pptr++]^=a>>8&255;rng_pool[rng_pptr++]^=a>>16&255;rng_pool[rng_pptr++]^=a>>24&255;rng_pptr>=rng_psize&&(rng_pptr-=rng_psize)}function rng_seed_time(){rng_seed_int((new Date).getTime())}
if(rng_pool==null){rng_pool=[];rng_pptr=0;var t;if(navigator.appName=="Netscape"&&navigator.appVersion<"5"&&window.crypto){var z=window.crypto.random(32);for(t=0;t<z.length;++t)rng_pool[rng_pptr++]=z.charCodeAt(t)&255}for(;rng_pptr<rng_psize;)t=Math.floor(65536*Math.random()),rng_pool[rng_pptr++]=t>>>8,rng_pool[rng_pptr++]=t&255;rng_pptr=0;rng_seed_time()}
function rng_get_byte(){if(rng_state==null){rng_seed_time();rng_state=prng_newstate();rng_state.init(rng_pool);for(rng_pptr=0;rng_pptr<rng_pool.length;++rng_pptr)rng_pool[rng_pptr]=0;rng_pptr=0}return rng_state.next()}function rng_get_bytes(a){var b;for(b=0;b<a.length;++b)a[b]=rng_get_byte()}function SecureRandom(){}SecureRandom.prototype.nextBytes=rng_get_bytes;
function SHA256(a){function b(a,b){var c=(a&65535)+(b&65535);return(a>>16)+(b>>16)+(c>>16)<<16|c&65535}function c(a,b){return a>>>b|a<<32-b}a=function(a){for(var a=a.replace(/\r\n/g,"\n"),b="",c=0;c<a.length;c++){var h=a.charCodeAt(c);h<128?b+=String.fromCharCode(h):(h>127&&h<2048?b+=String.fromCharCode(h>>6|192):(b+=String.fromCharCode(h>>12|224),b+=String.fromCharCode(h>>6&63|128)),b+=String.fromCharCode(h&63|128))}return b}(a);return function(a){for(var b="",c=0;c<a.length*4;c++)b+="0123456789abcdef".charAt(a[c>>
2]>>(3-c%4)*8+4&15)+"0123456789abcdef".charAt(a[c>>2]>>(3-c%4)*8&15);return b}(function(a,e){var g=[1116352408,1899447441,3049323471,3921009573,961987163,1508970993,2453635748,2870763221,3624381080,310598401,607225278,1426881987,1925078388,2162078206,2614888103,3248222580,3835390401,4022224774,264347078,604807628,770255983,1249150122,1555081692,1996064986,2554220882,2821834349,2952996808,3210313671,3336571891,3584528711,113926993,338241895,666307205,773529912,1294757372,1396182291,1695183700,1986661051,
2177026350,2456956037,2730485921,2820302411,3259730800,3345764771,3516065817,3600352804,4094571909,275423344,430227734,506948616,659060556,883997877,958139571,1322822218,1537002063,1747873779,1955562222,2024104815,2227730452,2361852424,2428436474,2756734187,3204031479,3329325298],h=[1779033703,3144134277,1013904242,2773480762,1359893119,2600822924,528734635,1541459225],f=Array(64),o,p,q,n,k,j,l,m,s,r,u,w;a[e>>5]|=128<<24-e%32;a[(e+64>>9<<4)+15]=e;for(s=0;s<a.length;s+=16){o=h[0];p=h[1];q=h[2];n=h[3];
k=h[4];j=h[5];l=h[6];m=h[7];for(r=0;r<64;r++)f[r]=r<16?a[r+s]:b(b(b(c(f[r-2],17)^c(f[r-2],19)^f[r-2]>>>10,f[r-7]),c(f[r-15],7)^c(f[r-15],18)^f[r-15]>>>3),f[r-16]),u=b(b(b(b(m,c(k,6)^c(k,11)^c(k,25)),k&j^~k&l),g[r]),f[r]),w=b(c(o,2)^c(o,13)^c(o,22),o&p^o&q^p&q),m=l,l=j,j=k,k=b(n,u),n=q,q=p,p=o,o=b(u,w);h[0]=b(o,h[0]);h[1]=b(p,h[1]);h[2]=b(q,h[2]);h[3]=b(n,h[3]);h[4]=b(k,h[4]);h[5]=b(j,h[5]);h[6]=b(l,h[6]);h[7]=b(m,h[7])}return h}(function(a){for(var b=[],c=0;c<a.length*8;c+=8)b[c>>5]|=(a.charCodeAt(c/
8)&255)<<24-c%32;return b}(a),a.length*8))}var sha256={hex:function(a){return SHA256(a)}};
function SHA1(a){function b(a,b){return a<<b|a>>>32-b}function c(a){var b="",c,d;for(c=7;c>=0;c--)d=a>>>c*4&15,b+=d.toString(16);return b}var d,e,g=Array(80),h=1732584193,f=4023233417,o=2562383102,p=271733878,q=3285377520,n,k,j,l,m,a=function(a){for(var a=a.replace(/\r\n/g,"\n"),b="",c=0;c<a.length;c++){var d=a.charCodeAt(c);d<128?b+=String.fromCharCode(d):(d>127&&d<2048?b+=String.fromCharCode(d>>6|192):(b+=String.fromCharCode(d>>12|224),b+=String.fromCharCode(d>>6&63|128)),b+=String.fromCharCode(d&
63|128))}return b}(a);n=a.length;var s=[];for(d=0;d<n-3;d+=4)e=a.charCodeAt(d)<<24|a.charCodeAt(d+1)<<16|a.charCodeAt(d+2)<<8|a.charCodeAt(d+3),s.push(e);switch(n%4){case 0:d=2147483648;break;case 1:d=a.charCodeAt(n-1)<<24|8388608;break;case 2:d=a.charCodeAt(n-2)<<24|a.charCodeAt(n-1)<<16|32768;break;case 3:d=a.charCodeAt(n-3)<<24|a.charCodeAt(n-2)<<16|a.charCodeAt(n-1)<<8|128}for(s.push(d);s.length%16!=14;)s.push(0);s.push(n>>>29);s.push(n<<3&4294967295);for(a=0;a<s.length;a+=16){for(d=0;d<16;d++)g[d]=
s[a+d];for(d=16;d<=79;d++)g[d]=b(g[d-3]^g[d-8]^g[d-14]^g[d-16],1);e=h;n=f;k=o;j=p;l=q;for(d=0;d<=19;d++)m=b(e,5)+(n&k|~n&j)+l+g[d]+1518500249&4294967295,l=j,j=k,k=b(n,30),n=e,e=m;for(d=20;d<=39;d++)m=b(e,5)+(n^k^j)+l+g[d]+1859775393&4294967295,l=j,j=k,k=b(n,30),n=e,e=m;for(d=40;d<=59;d++)m=b(e,5)+(n&k|n&j|k&j)+l+g[d]+2400959708&4294967295,l=j,j=k,k=b(n,30),n=e,e=m;for(d=60;d<=79;d++)m=b(e,5)+(n^k^j)+l+g[d]+3395469782&4294967295,l=j,j=k,k=b(n,30),n=e,e=m;h=h+e&4294967295;f=f+n&4294967295;o=o+k&4294967295;
p=p+j&4294967295;q=q+l&4294967295}m=c(h)+c(f)+c(o)+c(p)+c(q);return m.toLowerCase()}
var sha1={hex:function(a){return SHA1(a)}},MD5=function(a){function b(a,b){var c,d,e,f,g;e=a&2147483648;f=b&2147483648;c=a&1073741824;d=b&1073741824;g=(a&1073741823)+(b&1073741823);return c&d?g^2147483648^e^f:c|d?g&1073741824?g^3221225472^e^f:g^1073741824^e^f:g^e^f}function c(a,c,d,e,f,g,h){a=b(a,b(b(c&d|~c&e,f),h));return b(a<<g|a>>>32-g,c)}function d(a,c,d,e,f,g,h){a=b(a,b(b(c&e|d&~e,f),h));return b(a<<g|a>>>32-g,c)}function e(a,c,d,e,f,g,h){a=b(a,b(b(c^d^e,f),h));return b(a<<g|a>>>32-g,c)}function g(a,
c,d,e,f,g,h){a=b(a,b(b(d^(c|~e),f),h));return b(a<<g|a>>>32-g,c)}function h(a){var b="",c="",d;for(d=0;d<=3;d++)c=a>>>d*8&255,c="0"+c.toString(16),b+=c.substr(c.length-2,2);return b}var f=[],o,p,q,n,k,j,l,m,a=function(a){for(var a=a.replace(/\r\n/g,"\n"),b="",c=0;c<a.length;c++){var d=a.charCodeAt(c);d<128?b+=String.fromCharCode(d):(d>127&&d<2048?b+=String.fromCharCode(d>>6|192):(b+=String.fromCharCode(d>>12|224),b+=String.fromCharCode(d>>6&63|128)),b+=String.fromCharCode(d&63|128))}return b}(a),
f=function(a){var b,c=a.length;b=c+8;for(var d=((b-b%64)/64+1)*16,e=Array(d-1),f=0,g=0;g<c;)b=(g-g%4)/4,f=g%4*8,e[b]|=a.charCodeAt(g)<<f,g++;e[(g-g%4)/4]|=128<<g%4*8;e[d-2]=c<<3;e[d-1]=c>>>29;return e}(a);k=1732584193;j=4023233417;l=2562383102;m=271733878;for(a=0;a<f.length;a+=16)o=k,p=j,q=l,n=m,k=c(k,j,l,m,f[a+0],7,3614090360),m=c(m,k,j,l,f[a+1],12,3905402710),l=c(l,m,k,j,f[a+2],17,606105819),j=c(j,l,m,k,f[a+3],22,3250441966),k=c(k,j,l,m,f[a+4],7,4118548399),m=c(m,k,j,l,f[a+5],12,1200080426),l=c(l,
m,k,j,f[a+6],17,2821735955),j=c(j,l,m,k,f[a+7],22,4249261313),k=c(k,j,l,m,f[a+8],7,1770035416),m=c(m,k,j,l,f[a+9],12,2336552879),l=c(l,m,k,j,f[a+10],17,4294925233),j=c(j,l,m,k,f[a+11],22,2304563134),k=c(k,j,l,m,f[a+12],7,1804603682),m=c(m,k,j,l,f[a+13],12,4254626195),l=c(l,m,k,j,f[a+14],17,2792965006),j=c(j,l,m,k,f[a+15],22,1236535329),k=d(k,j,l,m,f[a+1],5,4129170786),m=d(m,k,j,l,f[a+6],9,3225465664),l=d(l,m,k,j,f[a+11],14,643717713),j=d(j,l,m,k,f[a+0],20,3921069994),k=d(k,j,l,m,f[a+5],5,3593408605),
m=d(m,k,j,l,f[a+10],9,38016083),l=d(l,m,k,j,f[a+15],14,3634488961),j=d(j,l,m,k,f[a+4],20,3889429448),k=d(k,j,l,m,f[a+9],5,568446438),m=d(m,k,j,l,f[a+14],9,3275163606),l=d(l,m,k,j,f[a+3],14,4107603335),j=d(j,l,m,k,f[a+8],20,1163531501),k=d(k,j,l,m,f[a+13],5,2850285829),m=d(m,k,j,l,f[a+2],9,4243563512),l=d(l,m,k,j,f[a+7],14,1735328473),j=d(j,l,m,k,f[a+12],20,2368359562),k=e(k,j,l,m,f[a+5],4,4294588738),m=e(m,k,j,l,f[a+8],11,2272392833),l=e(l,m,k,j,f[a+11],16,1839030562),j=e(j,l,m,k,f[a+14],23,4259657740),
k=e(k,j,l,m,f[a+1],4,2763975236),m=e(m,k,j,l,f[a+4],11,1272893353),l=e(l,m,k,j,f[a+7],16,4139469664),j=e(j,l,m,k,f[a+10],23,3200236656),k=e(k,j,l,m,f[a+13],4,681279174),m=e(m,k,j,l,f[a+0],11,3936430074),l=e(l,m,k,j,f[a+3],16,3572445317),j=e(j,l,m,k,f[a+6],23,76029189),k=e(k,j,l,m,f[a+9],4,3654602809),m=e(m,k,j,l,f[a+12],11,3873151461),l=e(l,m,k,j,f[a+15],16,530742520),j=e(j,l,m,k,f[a+2],23,3299628645),k=g(k,j,l,m,f[a+0],6,4096336452),m=g(m,k,j,l,f[a+7],10,1126891415),l=g(l,m,k,j,f[a+14],15,2878612391),
j=g(j,l,m,k,f[a+5],21,4237533241),k=g(k,j,l,m,f[a+12],6,1700485571),m=g(m,k,j,l,f[a+3],10,2399980690),l=g(l,m,k,j,f[a+10],15,4293915773),j=g(j,l,m,k,f[a+1],21,2240044497),k=g(k,j,l,m,f[a+8],6,1873313359),m=g(m,k,j,l,f[a+15],10,4264355552),l=g(l,m,k,j,f[a+6],15,2734768916),j=g(j,l,m,k,f[a+13],21,1309151649),k=g(k,j,l,m,f[a+4],6,4149444226),m=g(m,k,j,l,f[a+11],10,3174756917),l=g(l,m,k,j,f[a+2],15,718787259),j=g(j,l,m,k,f[a+9],21,3951481745),k=b(k,o),j=b(j,p),l=b(l,q),m=b(m,n);return(h(k)+h(j)+h(l)+
h(m)).toLowerCase()};function parseBigInt(a,b){return new BigInteger(a,b)}function linebrk(a,b){for(var c="",d=0;d+b<a.length;)c+=a.substring(d,d+b)+"\n",d+=b;return c+a.substring(d,a.length)}function byte2Hex(a){return a<16?"0"+a.toString(16):a.toString(16)}
function pkcs1pad2(a,b){if(b<a.length+11)throw"Message too long for RSA (n="+b+", l="+a.length+")";for(var c=[],d=a.length-1;d>=0&&b>0;){var e=a.charCodeAt(d--);e<128?c[--b]=e:e>127&&e<2048?(c[--b]=e&63|128,c[--b]=e>>6|192):(c[--b]=e&63|128,c[--b]=e>>6&63|128,c[--b]=e>>12|224)}c[--b]=0;d=new SecureRandom;for(e=[];b>2;){for(e[0]=0;e[0]==0;)d.nextBytes(e);c[--b]=e[0]}c[--b]=2;c[--b]=0;return new BigInteger(c)}
function RSAKey(){this.n=null;this.e=0;this.coeff=this.dmq1=this.dmp1=this.q=this.p=this.d=null}function RSASetPublic(a,b){a!=null&&b!=null&&a.length>0&&b.length>0?(this.n=parseBigInt(a,16),this.e=parseInt(b,16)):alert("Invalid RSA public key")}function RSADoPublic(a){return a.modPowInt(this.e,this.n)}function RSAEncrypt(a){a=pkcs1pad2(a,this.n.bitLength()+7>>3);if(a==null)return null;a=this.doPublic(a);if(a==null)return null;a=a.toString(16);return(a.length&1)==0?a:"0"+a}
RSAKey.prototype.doPublic=RSADoPublic;RSAKey.prototype.setPublic=RSASetPublic;RSAKey.prototype.encrypt=RSAEncrypt;function pkcs1unpad2(a,b){for(var c=a.toByteArray(),d=0;d<c.length&&c[d]==0;)++d;if(c.length-d!=b-1||c[d]!=2)return null;for(++d;c[d]!=0;)if(++d>=c.length)return null;for(var e="";++d<c.length;){var g=c[d]&255;g<128?e+=String.fromCharCode(g):g>191&&g<224?(e+=String.fromCharCode((g&31)<<6|c[d+1]&63),++d):(e+=String.fromCharCode((g&15)<<12|(c[d+1]&63)<<6|c[d+2]&63),d+=2)}return e}
function RSASetPrivate(a,b,c){a!=null&&b!=null&&a.length>0&&b.length>0?(this.n=parseBigInt(a,16),this.e=parseInt(b,16),this.d=parseBigInt(c,16)):alert("Invalid RSA private key")}
function RSASetPrivateEx(a,b,c,d,e,g,h,f){a!=null&&b!=null&&a.length>0&&b.length>0?(this.n=parseBigInt(a,16),this.e=parseInt(b,16),this.d=parseBigInt(c,16),this.p=parseBigInt(d,16),this.q=parseBigInt(e,16),this.dmp1=parseBigInt(g,16),this.dmq1=parseBigInt(h,16),this.coeff=parseBigInt(f,16)):alert("Invalid RSA private key")}
function RSAGenerate(a,b){var c=new SeededRandom,d=a>>1;this.e=parseInt(b,16);for(var e=new BigInteger(b,16);;){for(;;)if(this.p=new BigInteger(a-d,1,c),this.p.subtract(BigInteger.ONE).gcd(e).compareTo(BigInteger.ONE)==0&&this.p.isProbablePrime(10))break;for(;;)if(this.q=new BigInteger(d,1,c),this.q.subtract(BigInteger.ONE).gcd(e).compareTo(BigInteger.ONE)==0&&this.q.isProbablePrime(10))break;if(this.p.compareTo(this.q)<=0){var g=this.p;this.p=this.q;this.q=g}var g=this.p.subtract(BigInteger.ONE),
h=this.q.subtract(BigInteger.ONE),f=g.multiply(h);if(f.gcd(e).compareTo(BigInteger.ONE)==0){this.n=this.p.multiply(this.q);this.d=e.modInverse(f);this.dmp1=this.d.mod(g);this.dmq1=this.d.mod(h);this.coeff=this.q.modInverse(this.p);break}}}
function RSADoPrivate(a){if(this.p==null||this.q==null)return a.modPow(this.d,this.n);for(var b=a.mod(this.p).modPow(this.dmp1,this.p),a=a.mod(this.q).modPow(this.dmq1,this.q);b.compareTo(a)<0;)b=b.add(this.p);return b.subtract(a).multiply(this.coeff).mod(this.p).multiply(this.q).add(a)}function RSADecrypt(a){a=this.doPrivate(parseBigInt(a,16));return a==null?null:pkcs1unpad2(a,this.n.bitLength()+7>>3)}RSAKey.prototype.doPrivate=RSADoPrivate;RSAKey.prototype.setPrivate=RSASetPrivate;
RSAKey.prototype.setPrivateEx=RSASetPrivateEx;RSAKey.prototype.generate=RSAGenerate;RSAKey.prototype.decrypt=RSADecrypt;var _RSASIGN_DIHEAD=[];_RSASIGN_DIHEAD.sha1="3021300906052b0e03021a05000414";_RSASIGN_DIHEAD.sha256="3031300d060960864801650304020105000420";var _RSASIGN_HASHHEXFUNC=[];_RSASIGN_HASHHEXFUNC.sha1=sha1.hex;_RSASIGN_HASHHEXFUNC.sha256=sha256.hex;
function _rsasign_getHexPaddedDigestInfoForString(a,b,c){b/=4;for(var a=(0,_RSASIGN_HASHHEXFUNC[c])(a),c="00"+_RSASIGN_DIHEAD[c]+a,a="",b=b-4-c.length,d=0;d<b;d+=2)a+="ff";return sPaddedMessageHex="0001"+a+c}function _rsasign_signString(a,b){var c=_rsasign_getHexPaddedDigestInfoForString(a,this.n.bitLength(),b);return this.doPrivate(parseBigInt(c,16)).toString(16)}
function _rsasign_signStringWithSHA1(a){a=_rsasign_getHexPaddedDigestInfoForString(a,this.n.bitLength(),"sha1");return this.doPrivate(parseBigInt(a,16)).toString(16)}function _rsasign_signStringWithSHA256(a){a=_rsasign_getHexPaddedDigestInfoForString(a,this.n.bitLength(),"sha256");return this.doPrivate(parseBigInt(a,16)).toString(16)}function _rsasign_getDecryptSignatureBI(a,b,c){var d=new RSAKey;d.setPublic(b,c);return d.doPublic(a)}
function _rsasign_getHexDigestInfoFromSig(a,b,c){return _rsasign_getDecryptSignatureBI(a,b,c).toString(16).replace(/^1f+00/,"")}function _rsasign_getAlgNameAndHashFromHexDisgestInfo(a){for(var b in _RSASIGN_DIHEAD){var c=_RSASIGN_DIHEAD[b],d=c.length;if(a.substring(0,d)==c)return[b,a.substring(d)]}return[]}
function _rsasign_verifySignatureWithArgs(a,b,c,d){b=_rsasign_getHexDigestInfoFromSig(b,c,d);c=_rsasign_getAlgNameAndHashFromHexDisgestInfo(b);if(c.length==0)return!1;b=c[1];a=(0,_RSASIGN_HASHHEXFUNC[c[0]])(a);return b==a}function _rsasign_verifyHexSignatureForMessage(a,b){var c=parseBigInt(a,16);return _rsasign_verifySignatureWithArgs(b,c,this.n.toString(16),this.e.toString(16))}
function _rsasign_verifyString(a,b){var b=b.replace(/[ \n]+/g,""),c=this.doPublic(parseBigInt(b,16)).toString(16).replace(/^1f+00/,""),d=_rsasign_getAlgNameAndHashFromHexDisgestInfo(c);if(d.length==0)return!1;c=d[1];d=(0,_RSASIGN_HASHHEXFUNC[d[0]])(a);return c==d}RSAKey.prototype.signString=_rsasign_signString;RSAKey.prototype.signStringWithSHA1=_rsasign_signStringWithSHA1;RSAKey.prototype.signStringWithSHA256=_rsasign_signStringWithSHA256;RSAKey.prototype.verifyString=_rsasign_verifyString;
RSAKey.prototype.verifyHexSignatureForMessage=_rsasign_verifyHexSignatureForMessage;
var aes=function(){var a={Sbox:[99,124,119,123,242,107,111,197,48,1,103,43,254,215,171,118,202,130,201,125,250,89,71,240,173,212,162,175,156,164,114,192,183,253,147,38,54,63,247,204,52,165,229,241,113,216,49,21,4,199,35,195,24,150,5,154,7,18,128,226,235,39,178,117,9,131,44,26,27,110,90,160,82,59,214,179,41,227,47,132,83,209,0,237,32,252,177,91,106,203,190,57,74,76,88,207,208,239,170,251,67,77,51,133,69,249,2,127,80,60,159,168,81,163,64,143,146,157,56,245,188,182,218,33,16,255,243,210,205,12,19,236,
95,151,68,23,196,167,126,61,100,93,25,115,96,129,79,220,34,42,144,136,70,238,184,20,222,94,11,219,224,50,58,10,73,6,36,92,194,211,172,98,145,149,228,121,231,200,55,109,141,213,78,169,108,86,244,234,101,122,174,8,186,120,37,46,28,166,180,198,232,221,116,31,75,189,139,138,112,62,181,102,72,3,246,14,97,53,87,185,134,193,29,158,225,248,152,17,105,217,142,148,155,30,135,233,206,85,40,223,140,161,137,13,191,230,66,104,65,153,45,15,176,84,187,22],ShiftRowTab:[0,5,10,15,4,9,14,3,8,13,2,7,12,1,6,11]};a.Init=
function(){a.Sbox_Inv=Array(256);for(var b=0;b<256;b++)a.Sbox_Inv[a.Sbox[b]]=b;a.ShiftRowTab_Inv=Array(16);for(b=0;b<16;b++)a.ShiftRowTab_Inv[a.ShiftRowTab[b]]=b;a.xtime=Array(256);for(b=0;b<128;b++)a.xtime[b]=b<<1,a.xtime[128+b]=b<<1^27};a.Done=function(){delete a.Sbox_Inv;delete a.ShiftRowTab_Inv;delete a.xtime};a.ExpandKey=function(b){var c=b.length,d,e=1;switch(c){case 16:d=176;break;case 24:d=208;break;case 32:d=240;break;default:alert("my.ExpandKey: Only key lengths of 16, 24 or 32 bytes allowed!")}for(var g=
c;g<d;g+=4){var h=b.slice(g-4,g);if(g%c==0){if(h=[a.Sbox[h[1]]^e,a.Sbox[h[2]],a.Sbox[h[3]],a.Sbox[h[0]]],(e<<=1)>=256)e^=283}else c>24&&g%c==16&&(h=[a.Sbox[h[0]],a.Sbox[h[1]],a.Sbox[h[2]],a.Sbox[h[3]]]);for(var f=0;f<4;f++)b[g+f]=b[g+f-c]^h[f]}};a.Encrypt=function(b,c){var d=c.length;a.AddRoundKey(b,c.slice(0,16));for(var e=16;e<d-16;e+=16)a.SubBytes(b,a.Sbox),a.ShiftRows(b,a.ShiftRowTab),a.MixColumns(b),a.AddRoundKey(b,c.slice(e,e+16));a.SubBytes(b,a.Sbox);a.ShiftRows(b,a.ShiftRowTab);a.AddRoundKey(b,
c.slice(e,d))};a.Decrypt=function(b,c){var d=c.length;a.AddRoundKey(b,c.slice(d-16,d));a.ShiftRows(b,a.ShiftRowTab_Inv);a.SubBytes(b,a.Sbox_Inv);for(d-=32;d>=16;d-=16)a.AddRoundKey(b,c.slice(d,d+16)),a.MixColumns_Inv(b),a.ShiftRows(b,a.ShiftRowTab_Inv),a.SubBytes(b,a.Sbox_Inv);a.AddRoundKey(b,c.slice(0,16))};a.SubBytes=function(a,c){for(var d=0;d<16;d++)a[d]=c[a[d]]};a.AddRoundKey=function(a,c){for(var d=0;d<16;d++)a[d]^=c[d]};a.ShiftRows=function(a,c){for(var d=[].concat(a),e=0;e<16;e++)a[e]=d[c[e]]};
a.MixColumns=function(b){for(var c=0;c<16;c+=4){var d=b[c+0],e=b[c+1],g=b[c+2],h=b[c+3],f=d^e^g^h;b[c+0]^=f^a.xtime[d^e];b[c+1]^=f^a.xtime[e^g];b[c+2]^=f^a.xtime[g^h];b[c+3]^=f^a.xtime[h^d]}};a.MixColumns_Inv=function(b){for(var c=0;c<16;c+=4){var d=b[c+0],e=b[c+1],g=b[c+2],h=b[c+3],f=d^e^g^h,o=a.xtime[f],p=a.xtime[a.xtime[o^d^g]]^f;f^=a.xtime[a.xtime[o^e^h]];b[c+0]^=p^a.xtime[d^e];b[c+1]^=f^a.xtime[e^g];b[c+2]^=p^a.xtime[g^h];b[c+3]^=f^a.xtime[h^d]}};return a}(),cryptico=function(){var a={};aes.Init();
a.b256to64=function(a){var c,d,e,g="",h=0,f=0,o=a.length;for(e=0;e<o;e++)d=a.charCodeAt(e),f==0?(g+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(d>>2&63),c=(d&3)<<4):f==1?(g+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(c|d>>4&15),c=(d&15)<<2):f==2&&(g+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(c|d>>6&3),h+=1,g+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(d&63)),h+=1,f+=1,f==3&&
(f=0);f>0&&(g+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(c),g+="=");f==1&&(g+="=");return g};a.b64to256=function(a){var c,d,e="",g=0,h=0,f=a.length;for(d=0;d<f;d++)c="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".indexOf(a.charAt(d)),c>=0&&(g&&(e+=String.fromCharCode(h|c>>6-g&255)),g=g+2&7,h=c<<g&255);return e};a.b16to64=function(a){var c,d,e="";a.length%2==1&&(a="0"+a);for(c=0;c+3<=a.length;c+=3)d=parseInt(a.substring(c,c+3),16),e+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(d>>
6)+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(d&63);c+1==a.length?(d=parseInt(a.substring(c,c+1),16),e+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(d<<2)):c+2==a.length&&(d=parseInt(a.substring(c,c+2),16),e+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(d>>2)+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt((d&3)<<4));for(;(e.length&3)>0;)e+="=";return e};a.b64to16=function(a){var c="",
d,e=0,g;for(d=0;d<a.length;++d){if(a.charAt(d)=="=")break;v="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".indexOf(a.charAt(d));v<0||(e==0?(c+=int2char(v>>2),g=v&3,e=1):e==1?(c+=int2char(g<<2|v>>4),g=v&15,e=2):e==2?(c+=int2char(g),c+=int2char(v>>2),g=v&3,e=3):(c+=int2char(g<<2|v>>4),c+=int2char(v&15),e=0))}e==1&&(c+=int2char(g<<2));return c};a.string2bytes=function(a){for(var c=[],d=0;d<a.length;d++)c.push(a.charCodeAt(d));return c};a.bytes2string=function(a){for(var c="",d=0;d<
a.length;d++)c+=String.fromCharCode(a[d]);return c};a.blockXOR=function(a,c){for(var d=Array(16),e=0;e<16;e++)d[e]=a[e]^c[e];return d};a.blockIV=function(){var a=new SecureRandom,c=Array(16);a.nextBytes(c);return c};a.pad16=function(a){var c=a.slice(0),d=(16-a.length%16)%16;for(i=a.length;i<a.length+d;i++)c.push(0);return c};a.depad=function(a){for(a=a.slice(0);a[a.length-1]==0;)a=a.slice(0,a.length-1);return a};a.encryptAESCBC=function(b,c){var d=c.slice(0);aes.ExpandKey(d);for(var e=a.string2bytes(b),
e=a.pad16(e),g=a.blockIV(),h=0;h<e.length/16;h++){var f=e.slice(h*16,h*16+16),o=g.slice(h*16,h*16+16),f=a.blockXOR(o,f);aes.Encrypt(f,d);g=g.concat(f)}d=a.bytes2string(g);return a.b256to64(d)};a.decryptAESCBC=function(b,c){var d=c.slice(0);aes.ExpandKey(d);for(var b=a.b64to256(b),e=a.string2bytes(b),g=[],h=1;h<e.length/16;h++){var f=e.slice(h*16,h*16+16),o=e.slice((h-1)*16,(h-1)*16+16);aes.Decrypt(f,d);f=a.blockXOR(o,f);g=g.concat(f)}g=a.depad(g);return a.bytes2string(g)};a.wrap60=function(a){for(var c=
"",d=0;d<a.length;d++)d%60==0&&d!=0&&(c+="\n"),c+=a[d];return c};a.generateAESKey=function(){var a=Array(16);(new SecureRandom).nextBytes(a);return a};a.generateRSAKey=function(a,c){Math.seedrandom(sha256.hex(a));var d=new RSAKey;d.generate(c,"10001");return d};a.publicKeyString=function(b){return pubkey=b.n.toString(16)};a.publicKeyID=function(a){return MD5(a)};a.publicKeyFromString=function(b){var b=b.split("|")[0],c=new RSAKey;c.setPublic(b,"10001");return c};a.encrypt=function(b,
c,d){var e="";try{var h=a.publicKeyFromString(c);e+=h.encrypt(b)+"?"}catch(f){return{status:"Invalid public key"}};return{status:"success",cipher:e}};a.decrypt=function(b,c){var d=b.split("?"),e=c.decrypt(d[0]);return{status:"success",plaintext:e,signature:"unsigned"}};return a}();
\ No newline at end of file
/*
CryptoJS v3.1.2
code.google.com/p/crypto-js
(c) 2009-2013 by Jeff Mott. All rights reserved.
code.google.com/p/crypto-js/wiki/License
*/
var CryptoJS=CryptoJS||function(u,p){var d={},l=d.lib={},s=function(){},t=l.Base={extend:function(a){s.prototype=this;var c=new s;a&&c.mixIn(a);c.hasOwnProperty("init")||(c.init=function(){c.$super.init.apply(this,arguments)});c.init.prototype=c;c.$super=this;return c},create:function(){var a=this.extend();a.init.apply(a,arguments);return a},init:function(){},mixIn:function(a){for(var c in a)a.hasOwnProperty(c)&&(this[c]=a[c]);a.hasOwnProperty("toString")&&(this.toString=a.toString)},clone:function(){return this.init.prototype.extend(this)}},
r=l.WordArray=t.extend({init:function(a,c){a=this.words=a||[];this.sigBytes=c!=p?c:4*a.length},toString:function(a){return(a||v).stringify(this)},concat:function(a){var c=this.words,e=a.words,j=this.sigBytes;a=a.sigBytes;this.clamp();if(j%4)for(var k=0;k<a;k++)c[j+k>>>2]|=(e[k>>>2]>>>24-8*(k%4)&255)<<24-8*((j+k)%4);else if(65535<e.length)for(k=0;k<a;k+=4)c[j+k>>>2]=e[k>>>2];else c.push.apply(c,e);this.sigBytes+=a;return this},clamp:function(){var a=this.words,c=this.sigBytes;a[c>>>2]&=4294967295<<
32-8*(c%4);a.length=u.ceil(c/4)},clone:function(){var a=t.clone.call(this);a.words=this.words.slice(0);return a},random:function(a){for(var c=[],e=0;e<a;e+=4)c.push(4294967296*u.random()|0);return new r.init(c,a)}}),w=d.enc={},v=w.Hex={stringify:function(a){var c=a.words;a=a.sigBytes;for(var e=[],j=0;j<a;j++){var k=c[j>>>2]>>>24-8*(j%4)&255;e.push((k>>>4).toString(16));e.push((k&15).toString(16))}return e.join("")},parse:function(a){for(var c=a.length,e=[],j=0;j<c;j+=2)e[j>>>3]|=parseInt(a.substr(j,
2),16)<<24-4*(j%8);return new r.init(e,c/2)}},b=w.Latin1={stringify:function(a){var c=a.words;a=a.sigBytes;for(var e=[],j=0;j<a;j++)e.push(String.fromCharCode(c[j>>>2]>>>24-8*(j%4)&255));return e.join("")},parse:function(a){for(var c=a.length,e=[],j=0;j<c;j++)e[j>>>2]|=(a.charCodeAt(j)&255)<<24-8*(j%4);return new r.init(e,c)}},x=w.Utf8={stringify:function(a){try{return decodeURIComponent(escape(b.stringify(a)))}catch(c){throw Error("Malformed UTF-8 data");}},parse:function(a){return b.parse(unescape(encodeURIComponent(a)))}},
q=l.BufferedBlockAlgorithm=t.extend({reset:function(){this._data=new r.init;this._nDataBytes=0},_append:function(a){"string"==typeof a&&(a=x.parse(a));this._data.concat(a);this._nDataBytes+=a.sigBytes},_process:function(a){var c=this._data,e=c.words,j=c.sigBytes,k=this.blockSize,b=j/(4*k),b=a?u.ceil(b):u.max((b|0)-this._minBufferSize,0);a=b*k;j=u.min(4*a,j);if(a){for(var q=0;q<a;q+=k)this._doProcessBlock(e,q);q=e.splice(0,a);c.sigBytes-=j}return new r.init(q,j)},clone:function(){var a=t.clone.call(this);
a._data=this._data.clone();return a},_minBufferSize:0});l.Hasher=q.extend({cfg:t.extend(),init:function(a){this.cfg=this.cfg.extend(a);this.reset()},reset:function(){q.reset.call(this);this._doReset()},update:function(a){this._append(a);this._process();return this},finalize:function(a){a&&this._append(a);return this._doFinalize()},blockSize:16,_createHelper:function(a){return function(b,e){return(new a.init(e)).finalize(b)}},_createHmacHelper:function(a){return function(b,e){return(new n.HMAC.init(a,
e)).finalize(b)}}});var n=d.algo={};return d}(Math);
(function(){var u=CryptoJS,p=u.lib.WordArray;u.enc.Base64={stringify:function(d){var l=d.words,p=d.sigBytes,t=this._map;d.clamp();d=[];for(var r=0;r<p;r+=3)for(var w=(l[r>>>2]>>>24-8*(r%4)&255)<<16|(l[r+1>>>2]>>>24-8*((r+1)%4)&255)<<8|l[r+2>>>2]>>>24-8*((r+2)%4)&255,v=0;4>v&&r+0.75*v<p;v++)d.push(t.charAt(w>>>6*(3-v)&63));if(l=t.charAt(64))for(;d.length%4;)d.push(l);return d.join("")},parse:function(d){var l=d.length,s=this._map,t=s.charAt(64);t&&(t=d.indexOf(t),-1!=t&&(l=t));for(var t=[],r=0,w=0;w<
l;w++)if(w%4){var v=s.indexOf(d.charAt(w-1))<<2*(w%4),b=s.indexOf(d.charAt(w))>>>6-2*(w%4);t[r>>>2]|=(v|b)<<24-8*(r%4);r++}return p.create(t,r)},_map:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="}})();
(function(u){function p(b,n,a,c,e,j,k){b=b+(n&a|~n&c)+e+k;return(b<<j|b>>>32-j)+n}function d(b,n,a,c,e,j,k){b=b+(n&c|a&~c)+e+k;return(b<<j|b>>>32-j)+n}function l(b,n,a,c,e,j,k){b=b+(n^a^c)+e+k;return(b<<j|b>>>32-j)+n}function s(b,n,a,c,e,j,k){b=b+(a^(n|~c))+e+k;return(b<<j|b>>>32-j)+n}for(var t=CryptoJS,r=t.lib,w=r.WordArray,v=r.Hasher,r=t.algo,b=[],x=0;64>x;x++)b[x]=4294967296*u.abs(u.sin(x+1))|0;r=r.MD5=v.extend({_doReset:function(){this._hash=new w.init([1732584193,4023233417,2562383102,271733878])},
_doProcessBlock:function(q,n){for(var a=0;16>a;a++){var c=n+a,e=q[c];q[c]=(e<<8|e>>>24)&16711935|(e<<24|e>>>8)&4278255360}var a=this._hash.words,c=q[n+0],e=q[n+1],j=q[n+2],k=q[n+3],z=q[n+4],r=q[n+5],t=q[n+6],w=q[n+7],v=q[n+8],A=q[n+9],B=q[n+10],C=q[n+11],u=q[n+12],D=q[n+13],E=q[n+14],x=q[n+15],f=a[0],m=a[1],g=a[2],h=a[3],f=p(f,m,g,h,c,7,b[0]),h=p(h,f,m,g,e,12,b[1]),g=p(g,h,f,m,j,17,b[2]),m=p(m,g,h,f,k,22,b[3]),f=p(f,m,g,h,z,7,b[4]),h=p(h,f,m,g,r,12,b[5]),g=p(g,h,f,m,t,17,b[6]),m=p(m,g,h,f,w,22,b[7]),
f=p(f,m,g,h,v,7,b[8]),h=p(h,f,m,g,A,12,b[9]),g=p(g,h,f,m,B,17,b[10]),m=p(m,g,h,f,C,22,b[11]),f=p(f,m,g,h,u,7,b[12]),h=p(h,f,m,g,D,12,b[13]),g=p(g,h,f,m,E,17,b[14]),m=p(m,g,h,f,x,22,b[15]),f=d(f,m,g,h,e,5,b[16]),h=d(h,f,m,g,t,9,b[17]),g=d(g,h,f,m,C,14,b[18]),m=d(m,g,h,f,c,20,b[19]),f=d(f,m,g,h,r,5,b[20]),h=d(h,f,m,g,B,9,b[21]),g=d(g,h,f,m,x,14,b[22]),m=d(m,g,h,f,z,20,b[23]),f=d(f,m,g,h,A,5,b[24]),h=d(h,f,m,g,E,9,b[25]),g=d(g,h,f,m,k,14,b[26]),m=d(m,g,h,f,v,20,b[27]),f=d(f,m,g,h,D,5,b[28]),h=d(h,f,
m,g,j,9,b[29]),g=d(g,h,f,m,w,14,b[30]),m=d(m,g,h,f,u,20,b[31]),f=l(f,m,g,h,r,4,b[32]),h=l(h,f,m,g,v,11,b[33]),g=l(g,h,f,m,C,16,b[34]),m=l(m,g,h,f,E,23,b[35]),f=l(f,m,g,h,e,4,b[36]),h=l(h,f,m,g,z,11,b[37]),g=l(g,h,f,m,w,16,b[38]),m=l(m,g,h,f,B,23,b[39]),f=l(f,m,g,h,D,4,b[40]),h=l(h,f,m,g,c,11,b[41]),g=l(g,h,f,m,k,16,b[42]),m=l(m,g,h,f,t,23,b[43]),f=l(f,m,g,h,A,4,b[44]),h=l(h,f,m,g,u,11,b[45]),g=l(g,h,f,m,x,16,b[46]),m=l(m,g,h,f,j,23,b[47]),f=s(f,m,g,h,c,6,b[48]),h=s(h,f,m,g,w,10,b[49]),g=s(g,h,f,m,
E,15,b[50]),m=s(m,g,h,f,r,21,b[51]),f=s(f,m,g,h,u,6,b[52]),h=s(h,f,m,g,k,10,b[53]),g=s(g,h,f,m,B,15,b[54]),m=s(m,g,h,f,e,21,b[55]),f=s(f,m,g,h,v,6,b[56]),h=s(h,f,m,g,x,10,b[57]),g=s(g,h,f,m,t,15,b[58]),m=s(m,g,h,f,D,21,b[59]),f=s(f,m,g,h,z,6,b[60]),h=s(h,f,m,g,C,10,b[61]),g=s(g,h,f,m,j,15,b[62]),m=s(m,g,h,f,A,21,b[63]);a[0]=a[0]+f|0;a[1]=a[1]+m|0;a[2]=a[2]+g|0;a[3]=a[3]+h|0},_doFinalize:function(){var b=this._data,n=b.words,a=8*this._nDataBytes,c=8*b.sigBytes;n[c>>>5]|=128<<24-c%32;var e=u.floor(a/
4294967296);n[(c+64>>>9<<4)+15]=(e<<8|e>>>24)&16711935|(e<<24|e>>>8)&4278255360;n[(c+64>>>9<<4)+14]=(a<<8|a>>>24)&16711935|(a<<24|a>>>8)&4278255360;b.sigBytes=4*(n.length+1);this._process();b=this._hash;n=b.words;for(a=0;4>a;a++)c=n[a],n[a]=(c<<8|c>>>24)&16711935|(c<<24|c>>>8)&4278255360;return b},clone:function(){var b=v.clone.call(this);b._hash=this._hash.clone();return b}});t.MD5=v._createHelper(r);t.HmacMD5=v._createHmacHelper(r)})(Math);
(function(){var u=CryptoJS,p=u.lib,d=p.Base,l=p.WordArray,p=u.algo,s=p.EvpKDF=d.extend({cfg:d.extend({keySize:4,hasher:p.MD5,iterations:1}),init:function(d){this.cfg=this.cfg.extend(d)},compute:function(d,r){for(var p=this.cfg,s=p.hasher.create(),b=l.create(),u=b.words,q=p.keySize,p=p.iterations;u.length<q;){n&&s.update(n);var n=s.update(d).finalize(r);s.reset();for(var a=1;a<p;a++)n=s.finalize(n),s.reset();b.concat(n)}b.sigBytes=4*q;return b}});u.EvpKDF=function(d,l,p){return s.create(p).compute(d,
l)}})();
CryptoJS.lib.Cipher||function(u){var p=CryptoJS,d=p.lib,l=d.Base,s=d.WordArray,t=d.BufferedBlockAlgorithm,r=p.enc.Base64,w=p.algo.EvpKDF,v=d.Cipher=t.extend({cfg:l.extend(),createEncryptor:function(e,a){return this.create(this._ENC_XFORM_MODE,e,a)},createDecryptor:function(e,a){return this.create(this._DEC_XFORM_MODE,e,a)},init:function(e,a,b){this.cfg=this.cfg.extend(b);this._xformMode=e;this._key=a;this.reset()},reset:function(){t.reset.call(this);this._doReset()},process:function(e){this._append(e);return this._process()},
finalize:function(e){e&&this._append(e);return this._doFinalize()},keySize:4,ivSize:4,_ENC_XFORM_MODE:1,_DEC_XFORM_MODE:2,_createHelper:function(e){return{encrypt:function(b,k,d){return("string"==typeof k?c:a).encrypt(e,b,k,d)},decrypt:function(b,k,d){return("string"==typeof k?c:a).decrypt(e,b,k,d)}}}});d.StreamCipher=v.extend({_doFinalize:function(){return this._process(!0)},blockSize:1});var b=p.mode={},x=function(e,a,b){var c=this._iv;c?this._iv=u:c=this._prevBlock;for(var d=0;d<b;d++)e[a+d]^=
c[d]},q=(d.BlockCipherMode=l.extend({createEncryptor:function(e,a){return this.Encryptor.create(e,a)},createDecryptor:function(e,a){return this.Decryptor.create(e,a)},init:function(e,a){this._cipher=e;this._iv=a}})).extend();q.Encryptor=q.extend({processBlock:function(e,a){var b=this._cipher,c=b.blockSize;x.call(this,e,a,c);b.encryptBlock(e,a);this._prevBlock=e.slice(a,a+c)}});q.Decryptor=q.extend({processBlock:function(e,a){var b=this._cipher,c=b.blockSize,d=e.slice(a,a+c);b.decryptBlock(e,a);x.call(this,
e,a,c);this._prevBlock=d}});b=b.CBC=q;q=(p.pad={}).Pkcs7={pad:function(a,b){for(var c=4*b,c=c-a.sigBytes%c,d=c<<24|c<<16|c<<8|c,l=[],n=0;n<c;n+=4)l.push(d);c=s.create(l,c);a.concat(c)},unpad:function(a){a.sigBytes-=a.words[a.sigBytes-1>>>2]&255}};d.BlockCipher=v.extend({cfg:v.cfg.extend({mode:b,padding:q}),reset:function(){v.reset.call(this);var a=this.cfg,b=a.iv,a=a.mode;if(this._xformMode==this._ENC_XFORM_MODE)var c=a.createEncryptor;else c=a.createDecryptor,this._minBufferSize=1;this._mode=c.call(a,
this,b&&b.words)},_doProcessBlock:function(a,b){this._mode.processBlock(a,b)},_doFinalize:function(){var a=this.cfg.padding;if(this._xformMode==this._ENC_XFORM_MODE){a.pad(this._data,this.blockSize);var b=this._process(!0)}else b=this._process(!0),a.unpad(b);return b},blockSize:4});var n=d.CipherParams=l.extend({init:function(a){this.mixIn(a)},toString:function(a){return(a||this.formatter).stringify(this)}}),b=(p.format={}).OpenSSL={stringify:function(a){var b=a.ciphertext;a=a.salt;return(a?s.create([1398893684,
1701076831]).concat(a).concat(b):b).toString(r)},parse:function(a){a=r.parse(a);var b=a.words;if(1398893684==b[0]&&1701076831==b[1]){var c=s.create(b.slice(2,4));b.splice(0,4);a.sigBytes-=16}return n.create({ciphertext:a,salt:c})}},a=d.SerializableCipher=l.extend({cfg:l.extend({format:b}),encrypt:function(a,b,c,d){d=this.cfg.extend(d);var l=a.createEncryptor(c,d);b=l.finalize(b);l=l.cfg;return n.create({ciphertext:b,key:c,iv:l.iv,algorithm:a,mode:l.mode,padding:l.padding,blockSize:a.blockSize,formatter:d.format})},
decrypt:function(a,b,c,d){d=this.cfg.extend(d);b=this._parse(b,d.format);return a.createDecryptor(c,d).finalize(b.ciphertext)},_parse:function(a,b){return"string"==typeof a?b.parse(a,this):a}}),p=(p.kdf={}).OpenSSL={execute:function(a,b,c,d){d||(d=s.random(8));a=w.create({keySize:b+c}).compute(a,d);c=s.create(a.words.slice(b),4*c);a.sigBytes=4*b;return n.create({key:a,iv:c,salt:d})}},c=d.PasswordBasedCipher=a.extend({cfg:a.cfg.extend({kdf:p}),encrypt:function(b,c,d,l){l=this.cfg.extend(l);d=l.kdf.execute(d,
b.keySize,b.ivSize);l.iv=d.iv;b=a.encrypt.call(this,b,c,d.key,l);b.mixIn(d);return b},decrypt:function(b,c,d,l){l=this.cfg.extend(l);c=this._parse(c,l.format);d=l.kdf.execute(d,b.keySize,b.ivSize,c.salt);l.iv=d.iv;return a.decrypt.call(this,b,c,d.key,l)}})}();
(function(){for(var u=CryptoJS,p=u.lib.BlockCipher,d=u.algo,l=[],s=[],t=[],r=[],w=[],v=[],b=[],x=[],q=[],n=[],a=[],c=0;256>c;c++)a[c]=128>c?c<<1:c<<1^283;for(var e=0,j=0,c=0;256>c;c++){var k=j^j<<1^j<<2^j<<3^j<<4,k=k>>>8^k&255^99;l[e]=k;s[k]=e;var z=a[e],F=a[z],G=a[F],y=257*a[k]^16843008*k;t[e]=y<<24|y>>>8;r[e]=y<<16|y>>>16;w[e]=y<<8|y>>>24;v[e]=y;y=16843009*G^65537*F^257*z^16843008*e;b[k]=y<<24|y>>>8;x[k]=y<<16|y>>>16;q[k]=y<<8|y>>>24;n[k]=y;e?(e=z^a[a[a[G^z]]],j^=a[a[j]]):e=j=1}var H=[0,1,2,4,8,
16,32,64,128,27,54],d=d.AES=p.extend({_doReset:function(){for(var a=this._key,c=a.words,d=a.sigBytes/4,a=4*((this._nRounds=d+6)+1),e=this._keySchedule=[],j=0;j<a;j++)if(j<d)e[j]=c[j];else{var k=e[j-1];j%d?6<d&&4==j%d&&(k=l[k>>>24]<<24|l[k>>>16&255]<<16|l[k>>>8&255]<<8|l[k&255]):(k=k<<8|k>>>24,k=l[k>>>24]<<24|l[k>>>16&255]<<16|l[k>>>8&255]<<8|l[k&255],k^=H[j/d|0]<<24);e[j]=e[j-d]^k}c=this._invKeySchedule=[];for(d=0;d<a;d++)j=a-d,k=d%4?e[j]:e[j-4],c[d]=4>d||4>=j?k:b[l[k>>>24]]^x[l[k>>>16&255]]^q[l[k>>>
8&255]]^n[l[k&255]]},encryptBlock:function(a,b){this._doCryptBlock(a,b,this._keySchedule,t,r,w,v,l)},decryptBlock:function(a,c){var d=a[c+1];a[c+1]=a[c+3];a[c+3]=d;this._doCryptBlock(a,c,this._invKeySchedule,b,x,q,n,s);d=a[c+1];a[c+1]=a[c+3];a[c+3]=d},_doCryptBlock:function(a,b,c,d,e,j,l,f){for(var m=this._nRounds,g=a[b]^c[0],h=a[b+1]^c[1],k=a[b+2]^c[2],n=a[b+3]^c[3],p=4,r=1;r<m;r++)var q=d[g>>>24]^e[h>>>16&255]^j[k>>>8&255]^l[n&255]^c[p++],s=d[h>>>24]^e[k>>>16&255]^j[n>>>8&255]^l[g&255]^c[p++],t=
d[k>>>24]^e[n>>>16&255]^j[g>>>8&255]^l[h&255]^c[p++],n=d[n>>>24]^e[g>>>16&255]^j[h>>>8&255]^l[k&255]^c[p++],g=q,h=s,k=t;q=(f[g>>>24]<<24|f[h>>>16&255]<<16|f[k>>>8&255]<<8|f[n&255])^c[p++];s=(f[h>>>24]<<24|f[k>>>16&255]<<16|f[n>>>8&255]<<8|f[g&255])^c[p++];t=(f[k>>>24]<<24|f[n>>>16&255]<<16|f[g>>>8&255]<<8|f[h&255])^c[p++];n=(f[n>>>24]<<24|f[g>>>16&255]<<16|f[h>>>8&255]<<8|f[k&255])^c[p++];a[b]=q;a[b+1]=s;a[b+2]=t;a[b+3]=n},keySize:8});u.AES=p._createHelper(d)})();
define(function(require, exports, module) {
var _oCommon, _oUtils, _oBase64;
require("websdk");
_oCommon = require("common");
_oUtils = require("utils");
_oBase64 = require("base64");
function EncryptionFac () {}
EncryptionFac.prototype.encrypt = function (oStr, iRSABits, bBase64Encrypted, cbFun) {
//var that = this;
var iBits = 1024;
if (iRSABits) {
iBits = iRSABits;
}
var szPassPhrase = new Date() + "",
szMattsRSAkey = cryptico.generateRSAKey(szPassPhrase, iBits),
szPublicKeyString = cryptico.publicKeyString(szMattsRSAkey),
szXml = "<?xml version='1.0' encoding='UTF-8'?><PublicKey><key>" + _oBase64.encode(szPublicKeyString) + "</key></PublicKey>",
oXmlDoc = _oUtils.parseXmlFromStr(szXml);
WebSDK.WSDK_Request(_oCommon.m_szHostName, _oCommon.m_iHttpProtocal, _oCommon.m_iHttpPort, {
cmd: "challenge",
type: "POST",
data: oXmlDoc,
success: function (status, xmlDoc) {
var szDecryptionResult = cryptico.decrypt(_oBase64.decode(_oUtils.nodeValue(xmlDoc, "key")), szMattsRSAkey);
if(szDecryptionResult.plaintext != null) {
var szKey,szEncryptPassword;
var aResult = [];
if (iBits === 256) {
szKey = _oUtils.toHex(szDecryptionResult.plaintext);
} else {
szKey = szDecryptionResult.plaintext;
}
szEncryptPassword = aes_encrypt(szDecryptionResult.plaintext.substring(0, 16), szKey, true);
if("function" === typeof cbFun) {
if("string" === typeof oStr) {
bBase64Encrypted && ( oStr = _oBase64.encode(oStr) );
cbFun( _oBase64.encode( szEncryptPassword + _oUtils.encodeAES(oStr, szKey, "", "ecb") ) );
} else if("[object Array]" === Object.prototype.toString.call(oStr)) {
for(var i = 0, iArrayLen = oStr.length; i < iArrayLen; i++) {
bBase64Encrypted && ( oStr[i] = _oBase64.encode(oStr[i]) );
var szTemp = szEncryptPassword + _oUtils.encodeAES(oStr[i], szKey, "", "ecb");
aResult.push( _oBase64.encode(szTemp) );
}
cbFun(aResult);
}
}
}
}
});
};
EncryptionFac.prototype.encryptSync = function (oStr, iRSABits, bBase64Encrypted) {
//var that = this;
var iBits = 1024;
var aResult = [];
if (iRSABits) {
iBits = iRSABits;
}
var szPassPhrase = new Date() + "",
szMattsRSAkey = cryptico.generateRSAKey(szPassPhrase, iBits),
szPublicKeyString = cryptico.publicKeyString(szMattsRSAkey),
szXml = "<?xml version='1.0' encoding='UTF-8'?><PublicKey><key>" + _oBase64.encode(szPublicKeyString) + "</key></PublicKey>",
oXmlDoc = _oUtils.parseXmlFromStr(szXml);
WebSDK.WSDK_Request(_oCommon.m_szHostName, _oCommon.m_iHttpProtocal, _oCommon.m_iHttpPort, {
cmd: "challenge",
type: "POST",
async: false,
data: oXmlDoc,
success: function (status, xmlDoc) {
var szDecryptionResult = cryptico.decrypt(_oBase64.decode(_oUtils.nodeValue(xmlDoc, "key")), szMattsRSAkey);
if(szDecryptionResult.plaintext != null) {
var szKey, szEncryptPassword;
if (iBits === 256) {
szKey = _oUtils.toHex(szDecryptionResult.plaintext);
} else {
szKey = szDecryptionResult.plaintext;
}
szEncryptPassword = aes_encrypt(szDecryptionResult.plaintext.substring(0, 16), szKey, true);
if("string" === typeof oStr) {
bBase64Encrypted && ( oStr = _oBase64.encode(oStr) );
aResult.push( _oBase64.encode( szEncryptPassword + _oUtils.encodeAES(oStr, szKey, "", "ecb") ) );
} else {
for(var i = 0, iArrayLen = oStr.length; i < iArrayLen; i++) {
bBase64Encrypted && ( oStr[i] = _oBase64.encode(oStr[i]) );
var szTemp = szEncryptPassword + _oUtils.encodeAES(oStr[i], szKey, "", "ecb");
aResult.push( _oBase64.encode(szTemp) );
}
}
}
}
});
if("string" === typeof oStr) {
return aResult[0];
} else {
return aResult;
}
};
module.exports = new EncryptionFac();
});
\ No newline at end of file
/*! jQuery v3.3.1 | (c) JS Foundation and other contributors | jquery.org/license */
!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(e,t){"use strict";var n=[],r=e.document,i=Object.getPrototypeOf,o=n.slice,a=n.concat,s=n.push,u=n.indexOf,l={},c=l.toString,f=l.hasOwnProperty,p=f.toString,d=p.call(Object),h={},g=function e(t){return"function"==typeof t&&"number"!=typeof t.nodeType},y=function e(t){return null!=t&&t===t.window},v={type:!0,src:!0,noModule:!0};function m(e,t,n){var i,o=(t=t||r).createElement("script");if(o.text=e,n)for(i in v)n[i]&&(o[i]=n[i]);t.head.appendChild(o).parentNode.removeChild(o)}function x(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?l[c.call(e)]||"object":typeof e}var b="3.3.1",w=function(e,t){return new w.fn.init(e,t)},T=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g;w.fn=w.prototype={jquery:"3.3.1",constructor:w,length:0,toArray:function(){return o.call(this)},get:function(e){return null==e?o.call(this):e<0?this[e+this.length]:this[e]},pushStack:function(e){var t=w.merge(this.constructor(),e);return t.prevObject=this,t},each:function(e){return w.each(this,e)},map:function(e){return this.pushStack(w.map(this,function(t,n){return e.call(t,n,t)}))},slice:function(){return this.pushStack(o.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(e<0?t:0);return this.pushStack(n>=0&&n<t?[this[n]]:[])},end:function(){return this.prevObject||this.constructor()},push:s,sort:n.sort,splice:n.splice},w.extend=w.fn.extend=function(){var e,t,n,r,i,o,a=arguments[0]||{},s=1,u=arguments.length,l=!1;for("boolean"==typeof a&&(l=a,a=arguments[s]||{},s++),"object"==typeof a||g(a)||(a={}),s===u&&(a=this,s--);s<u;s++)if(null!=(e=arguments[s]))for(t in e)n=a[t],a!==(r=e[t])&&(l&&r&&(w.isPlainObject(r)||(i=Array.isArray(r)))?(i?(i=!1,o=n&&Array.isArray(n)?n:[]):o=n&&w.isPlainObject(n)?n:{},a[t]=w.extend(l,o,r)):void 0!==r&&(a[t]=r));return a},w.extend({expando:"jQuery"+("3.3.1"+Math.random()).replace(/\D/g,""),isReady:!0,error:function(e){throw new Error(e)},noop:function(){},isPlainObject:function(e){var t,n;return!(!e||"[object Object]"!==c.call(e))&&(!(t=i(e))||"function"==typeof(n=f.call(t,"constructor")&&t.constructor)&&p.call(n)===d)},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},globalEval:function(e){m(e)},each:function(e,t){var n,r=0;if(C(e)){for(n=e.length;r<n;r++)if(!1===t.call(e[r],r,e[r]))break}else for(r in e)if(!1===t.call(e[r],r,e[r]))break;return e},trim:function(e){return null==e?"":(e+"").replace(T,"")},makeArray:function(e,t){var n=t||[];return null!=e&&(C(Object(e))?w.merge(n,"string"==typeof e?[e]:e):s.call(n,e)),n},inArray:function(e,t,n){return null==t?-1:u.call(t,e,n)},merge:function(e,t){for(var n=+t.length,r=0,i=e.length;r<n;r++)e[i++]=t[r];return e.length=i,e},grep:function(e,t,n){for(var r,i=[],o=0,a=e.length,s=!n;o<a;o++)(r=!t(e[o],o))!==s&&i.push(e[o]);return i},map:function(e,t,n){var r,i,o=0,s=[];if(C(e))for(r=e.length;o<r;o++)null!=(i=t(e[o],o,n))&&s.push(i);else for(o in e)null!=(i=t(e[o],o,n))&&s.push(i);return a.apply([],s)},guid:1,support:h}),"function"==typeof Symbol&&(w.fn[Symbol.iterator]=n[Symbol.iterator]),w.each("Boolean Number String Function Array Date RegExp Object Error Symbol".split(" "),function(e,t){l["[object "+t+"]"]=t.toLowerCase()});function C(e){var t=!!e&&"length"in e&&e.length,n=x(e);return!g(e)&&!y(e)&&("array"===n||0===t||"number"==typeof t&&t>0&&t-1 in e)}var E=function(e){var t,n,r,i,o,a,s,u,l,c,f,p,d,h,g,y,v,m,x,b="sizzle"+1*new Date,w=e.document,T=0,C=0,E=ae(),k=ae(),S=ae(),D=function(e,t){return e===t&&(f=!0),0},N={}.hasOwnProperty,A=[],j=A.pop,q=A.push,L=A.push,H=A.slice,O=function(e,t){for(var n=0,r=e.length;n<r;n++)if(e[n]===t)return n;return-1},P="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",M="[\\x20\\t\\r\\n\\f]",R="(?:\\\\.|[\\w-]|[^\0-\\xa0])+",I="\\["+M+"*("+R+")(?:"+M+"*([*^$|!~]?=)"+M+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+R+"))|)"+M+"*\\]",W=":("+R+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+I+")*)|.*)\\)|)",$=new RegExp(M+"+","g"),B=new RegExp("^"+M+"+|((?:^|[^\\\\])(?:\\\\.)*)"+M+"+$","g"),F=new RegExp("^"+M+"*,"+M+"*"),_=new RegExp("^"+M+"*([>+~]|"+M+")"+M+"*"),z=new RegExp("="+M+"*([^\\]'\"]*?)"+M+"*\\]","g"),X=new RegExp(W),U=new RegExp("^"+R+"$"),V={ID:new RegExp("^#("+R+")"),CLASS:new RegExp("^\\.("+R+")"),TAG:new RegExp("^("+R+"|[*])"),ATTR:new RegExp("^"+I),PSEUDO:new RegExp("^"+W),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+P+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},G=/^(?:input|select|textarea|button)$/i,Y=/^h\d$/i,Q=/^[^{]+\{\s*\[native \w/,J=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,K=/[+~]/,Z=new RegExp("\\\\([\\da-f]{1,6}"+M+"?|("+M+")|.)","ig"),ee=function(e,t,n){var r="0x"+t-65536;return r!==r||n?t:r<0?String.fromCharCode(r+65536):String.fromCharCode(r>>10|55296,1023&r|56320)},te=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ne=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},re=function(){p()},ie=me(function(e){return!0===e.disabled&&("form"in e||"label"in e)},{dir:"parentNode",next:"legend"});try{L.apply(A=H.call(w.childNodes),w.childNodes),A[w.childNodes.length].nodeType}catch(e){L={apply:A.length?function(e,t){q.apply(e,H.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function oe(e,t,r,i){var o,s,l,c,f,h,v,m=t&&t.ownerDocument,T=t?t.nodeType:9;if(r=r||[],"string"!=typeof e||!e||1!==T&&9!==T&&11!==T)return r;if(!i&&((t?t.ownerDocument||t:w)!==d&&p(t),t=t||d,g)){if(11!==T&&(f=J.exec(e)))if(o=f[1]){if(9===T){if(!(l=t.getElementById(o)))return r;if(l.id===o)return r.push(l),r}else if(m&&(l=m.getElementById(o))&&x(t,l)&&l.id===o)return r.push(l),r}else{if(f[2])return L.apply(r,t.getElementsByTagName(e)),r;if((o=f[3])&&n.getElementsByClassName&&t.getElementsByClassName)return L.apply(r,t.getElementsByClassName(o)),r}if(n.qsa&&!S[e+" "]&&(!y||!y.test(e))){if(1!==T)m=t,v=e;else if("object"!==t.nodeName.toLowerCase()){(c=t.getAttribute("id"))?c=c.replace(te,ne):t.setAttribute("id",c=b),s=(h=a(e)).length;while(s--)h[s]="#"+c+" "+ve(h[s]);v=h.join(","),m=K.test(e)&&ge(t.parentNode)||t}if(v)try{return L.apply(r,m.querySelectorAll(v)),r}catch(e){}finally{c===b&&t.removeAttribute("id")}}}return u(e.replace(B,"$1"),t,r,i)}function ae(){var e=[];function t(n,i){return e.push(n+" ")>r.cacheLength&&delete t[e.shift()],t[n+" "]=i}return t}function se(e){return e[b]=!0,e}function ue(e){var t=d.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function le(e,t){var n=e.split("|"),i=n.length;while(i--)r.attrHandle[n[i]]=t}function ce(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function fe(e){return function(t){return"input"===t.nodeName.toLowerCase()&&t.type===e}}function pe(e){return function(t){var n=t.nodeName.toLowerCase();return("input"===n||"button"===n)&&t.type===e}}function de(e){return function(t){return"form"in t?t.parentNode&&!1===t.disabled?"label"in t?"label"in t.parentNode?t.parentNode.disabled===e:t.disabled===e:t.isDisabled===e||t.isDisabled!==!e&&ie(t)===e:t.disabled===e:"label"in t&&t.disabled===e}}function he(e){return se(function(t){return t=+t,se(function(n,r){var i,o=e([],n.length,t),a=o.length;while(a--)n[i=o[a]]&&(n[i]=!(r[i]=n[i]))})})}function ge(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}n=oe.support={},o=oe.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return!!t&&"HTML"!==t.nodeName},p=oe.setDocument=function(e){var t,i,a=e?e.ownerDocument||e:w;return a!==d&&9===a.nodeType&&a.documentElement?(d=a,h=d.documentElement,g=!o(d),w!==d&&(i=d.defaultView)&&i.top!==i&&(i.addEventListener?i.addEventListener("unload",re,!1):i.attachEvent&&i.attachEvent("onunload",re)),n.attributes=ue(function(e){return e.className="i",!e.getAttribute("className")}),n.getElementsByTagName=ue(function(e){return e.appendChild(d.createComment("")),!e.getElementsByTagName("*").length}),n.getElementsByClassName=Q.test(d.getElementsByClassName),n.getById=ue(function(e){return h.appendChild(e).id=b,!d.getElementsByName||!d.getElementsByName(b).length}),n.getById?(r.filter.ID=function(e){var t=e.replace(Z,ee);return function(e){return e.getAttribute("id")===t}},r.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&g){var n=t.getElementById(e);return n?[n]:[]}}):(r.filter.ID=function(e){var t=e.replace(Z,ee);return function(e){var n="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return n&&n.value===t}},r.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&g){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),r.find.TAG=n.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):n.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},r.find.CLASS=n.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&g)return t.getElementsByClassName(e)},v=[],y=[],(n.qsa=Q.test(d.querySelectorAll))&&(ue(function(e){h.appendChild(e).innerHTML="<a id='"+b+"'></a><select id='"+b+"-\r\\' msallowcapture=''><option selected=''></option></select>",e.querySelectorAll("[msallowcapture^='']").length&&y.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||y.push("\\["+M+"*(?:value|"+P+")"),e.querySelectorAll("[id~="+b+"-]").length||y.push("~="),e.querySelectorAll(":checked").length||y.push(":checked"),e.querySelectorAll("a#"+b+"+*").length||y.push(".#.+[+~]")}),ue(function(e){e.innerHTML="<a href='' disabled='disabled'></a><select disabled='disabled'><option/></select>";var t=d.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&y.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&y.push(":enabled",":disabled"),h.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&y.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),y.push(",.*:")})),(n.matchesSelector=Q.test(m=h.matches||h.webkitMatchesSelector||h.mozMatchesSelector||h.oMatchesSelector||h.msMatchesSelector))&&ue(function(e){n.disconnectedMatch=m.call(e,"*"),m.call(e,"[s!='']:x"),v.push("!=",W)}),y=y.length&&new RegExp(y.join("|")),v=v.length&&new RegExp(v.join("|")),t=Q.test(h.compareDocumentPosition),x=t||Q.test(h.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},D=t?function(e,t){if(e===t)return f=!0,0;var r=!e.compareDocumentPosition-!t.compareDocumentPosition;return r||(1&(r=(e.ownerDocument||e)===(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!n.sortDetached&&t.compareDocumentPosition(e)===r?e===d||e.ownerDocument===w&&x(w,e)?-1:t===d||t.ownerDocument===w&&x(w,t)?1:c?O(c,e)-O(c,t):0:4&r?-1:1)}:function(e,t){if(e===t)return f=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e===d?-1:t===d?1:i?-1:o?1:c?O(c,e)-O(c,t):0;if(i===o)return ce(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?ce(a[r],s[r]):a[r]===w?-1:s[r]===w?1:0},d):d},oe.matches=function(e,t){return oe(e,null,null,t)},oe.matchesSelector=function(e,t){if((e.ownerDocument||e)!==d&&p(e),t=t.replace(z,"='$1']"),n.matchesSelector&&g&&!S[t+" "]&&(!v||!v.test(t))&&(!y||!y.test(t)))try{var r=m.call(e,t);if(r||n.disconnectedMatch||e.document&&11!==e.document.nodeType)return r}catch(e){}return oe(t,d,null,[e]).length>0},oe.contains=function(e,t){return(e.ownerDocument||e)!==d&&p(e),x(e,t)},oe.attr=function(e,t){(e.ownerDocument||e)!==d&&p(e);var i=r.attrHandle[t.toLowerCase()],o=i&&N.call(r.attrHandle,t.toLowerCase())?i(e,t,!g):void 0;return void 0!==o?o:n.attributes||!g?e.getAttribute(t):(o=e.getAttributeNode(t))&&o.specified?o.value:null},oe.escape=function(e){return(e+"").replace(te,ne)},oe.error=function(e){throw new Error("Syntax error, unrecognized expression: "+e)},oe.uniqueSort=function(e){var t,r=[],i=0,o=0;if(f=!n.detectDuplicates,c=!n.sortStable&&e.slice(0),e.sort(D),f){while(t=e[o++])t===e[o]&&(i=r.push(o));while(i--)e.splice(r[i],1)}return c=null,e},i=oe.getText=function(e){var t,n="",r=0,o=e.nodeType;if(o){if(1===o||9===o||11===o){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=i(e)}else if(3===o||4===o)return e.nodeValue}else while(t=e[r++])n+=i(t);return n},(r=oe.selectors={cacheLength:50,createPseudo:se,match:V,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(Z,ee),e[3]=(e[3]||e[4]||e[5]||"").replace(Z,ee),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||oe.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&oe.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return V.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=a(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(Z,ee).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=E[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&E(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(e,t,n){return function(r){var i=oe.attr(r,e);return null==i?"!="===t:!t||(i+="","="===t?i===n:"!="===t?i!==n:"^="===t?n&&0===i.indexOf(n):"*="===t?n&&i.indexOf(n)>-1:"$="===t?n&&i.slice(-n.length)===n:"~="===t?(" "+i.replace($," ")+" ").indexOf(n)>-1:"|="===t&&(i===n||i.slice(0,n.length+1)===n+"-"))}},CHILD:function(e,t,n,r,i){var o="nth"!==e.slice(0,3),a="last"!==e.slice(-4),s="of-type"===t;return 1===r&&0===i?function(e){return!!e.parentNode}:function(t,n,u){var l,c,f,p,d,h,g=o!==a?"nextSibling":"previousSibling",y=t.parentNode,v=s&&t.nodeName.toLowerCase(),m=!u&&!s,x=!1;if(y){if(o){while(g){p=t;while(p=p[g])if(s?p.nodeName.toLowerCase()===v:1===p.nodeType)return!1;h=g="only"===e&&!h&&"nextSibling"}return!0}if(h=[a?y.firstChild:y.lastChild],a&&m){x=(d=(l=(c=(f=(p=y)[b]||(p[b]={}))[p.uniqueID]||(f[p.uniqueID]={}))[e]||[])[0]===T&&l[1])&&l[2],p=d&&y.childNodes[d];while(p=++d&&p&&p[g]||(x=d=0)||h.pop())if(1===p.nodeType&&++x&&p===t){c[e]=[T,d,x];break}}else if(m&&(x=d=(l=(c=(f=(p=t)[b]||(p[b]={}))[p.uniqueID]||(f[p.uniqueID]={}))[e]||[])[0]===T&&l[1]),!1===x)while(p=++d&&p&&p[g]||(x=d=0)||h.pop())if((s?p.nodeName.toLowerCase()===v:1===p.nodeType)&&++x&&(m&&((c=(f=p[b]||(p[b]={}))[p.uniqueID]||(f[p.uniqueID]={}))[e]=[T,x]),p===t))break;return(x-=i)===r||x%r==0&&x/r>=0}}},PSEUDO:function(e,t){var n,i=r.pseudos[e]||r.setFilters[e.toLowerCase()]||oe.error("unsupported pseudo: "+e);return i[b]?i(t):i.length>1?(n=[e,e,"",t],r.setFilters.hasOwnProperty(e.toLowerCase())?se(function(e,n){var r,o=i(e,t),a=o.length;while(a--)e[r=O(e,o[a])]=!(n[r]=o[a])}):function(e){return i(e,0,n)}):i}},pseudos:{not:se(function(e){var t=[],n=[],r=s(e.replace(B,"$1"));return r[b]?se(function(e,t,n,i){var o,a=r(e,null,i,[]),s=e.length;while(s--)(o=a[s])&&(e[s]=!(t[s]=o))}):function(e,i,o){return t[0]=e,r(t,null,o,n),t[0]=null,!n.pop()}}),has:se(function(e){return function(t){return oe(e,t).length>0}}),contains:se(function(e){return e=e.replace(Z,ee),function(t){return(t.textContent||t.innerText||i(t)).indexOf(e)>-1}}),lang:se(function(e){return U.test(e||"")||oe.error("unsupported lang: "+e),e=e.replace(Z,ee).toLowerCase(),function(t){var n;do{if(n=g?t.lang:t.getAttribute("xml:lang")||t.getAttribute("lang"))return(n=n.toLowerCase())===e||0===n.indexOf(e+"-")}while((t=t.parentNode)&&1===t.nodeType);return!1}}),target:function(t){var n=e.location&&e.location.hash;return n&&n.slice(1)===t.id},root:function(e){return e===h},focus:function(e){return e===d.activeElement&&(!d.hasFocus||d.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:de(!1),disabled:de(!0),checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,!0===e.selected},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeType<6)return!1;return!0},parent:function(e){return!r.pseudos.empty(e)},header:function(e){return Y.test(e.nodeName)},input:function(e){return G.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||"text"===t.toLowerCase())},first:he(function(){return[0]}),last:he(function(e,t){return[t-1]}),eq:he(function(e,t,n){return[n<0?n+t:n]}),even:he(function(e,t){for(var n=0;n<t;n+=2)e.push(n);return e}),odd:he(function(e,t){for(var n=1;n<t;n+=2)e.push(n);return e}),lt:he(function(e,t,n){for(var r=n<0?n+t:n;--r>=0;)e.push(r);return e}),gt:he(function(e,t,n){for(var r=n<0?n+t:n;++r<t;)e.push(r);return e})}}).pseudos.nth=r.pseudos.eq;for(t in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})r.pseudos[t]=fe(t);for(t in{submit:!0,reset:!0})r.pseudos[t]=pe(t);function ye(){}ye.prototype=r.filters=r.pseudos,r.setFilters=new ye,a=oe.tokenize=function(e,t){var n,i,o,a,s,u,l,c=k[e+" "];if(c)return t?0:c.slice(0);s=e,u=[],l=r.preFilter;while(s){n&&!(i=F.exec(s))||(i&&(s=s.slice(i[0].length)||s),u.push(o=[])),n=!1,(i=_.exec(s))&&(n=i.shift(),o.push({value:n,type:i[0].replace(B," ")}),s=s.slice(n.length));for(a in r.filter)!(i=V[a].exec(s))||l[a]&&!(i=l[a](i))||(n=i.shift(),o.push({value:n,type:a,matches:i}),s=s.slice(n.length));if(!n)break}return t?s.length:s?oe.error(e):k(e,u).slice(0)};function ve(e){for(var t=0,n=e.length,r="";t<n;t++)r+=e[t].value;return r}function me(e,t,n){var r=t.dir,i=t.next,o=i||r,a=n&&"parentNode"===o,s=C++;return t.first?function(t,n,i){while(t=t[r])if(1===t.nodeType||a)return e(t,n,i);return!1}:function(t,n,u){var l,c,f,p=[T,s];if(u){while(t=t[r])if((1===t.nodeType||a)&&e(t,n,u))return!0}else while(t=t[r])if(1===t.nodeType||a)if(f=t[b]||(t[b]={}),c=f[t.uniqueID]||(f[t.uniqueID]={}),i&&i===t.nodeName.toLowerCase())t=t[r]||t;else{if((l=c[o])&&l[0]===T&&l[1]===s)return p[2]=l[2];if(c[o]=p,p[2]=e(t,n,u))return!0}return!1}}function xe(e){return e.length>1?function(t,n,r){var i=e.length;while(i--)if(!e[i](t,n,r))return!1;return!0}:e[0]}function be(e,t,n){for(var r=0,i=t.length;r<i;r++)oe(e,t[r],n);return n}function we(e,t,n,r,i){for(var o,a=[],s=0,u=e.length,l=null!=t;s<u;s++)(o=e[s])&&(n&&!n(o,r,i)||(a.push(o),l&&t.push(s)));return a}function Te(e,t,n,r,i,o){return r&&!r[b]&&(r=Te(r)),i&&!i[b]&&(i=Te(i,o)),se(function(o,a,s,u){var l,c,f,p=[],d=[],h=a.length,g=o||be(t||"*",s.nodeType?[s]:s,[]),y=!e||!o&&t?g:we(g,p,e,s,u),v=n?i||(o?e:h||r)?[]:a:y;if(n&&n(y,v,s,u),r){l=we(v,d),r(l,[],s,u),c=l.length;while(c--)(f=l[c])&&(v[d[c]]=!(y[d[c]]=f))}if(o){if(i||e){if(i){l=[],c=v.length;while(c--)(f=v[c])&&l.push(y[c]=f);i(null,v=[],l,u)}c=v.length;while(c--)(f=v[c])&&(l=i?O(o,f):p[c])>-1&&(o[l]=!(a[l]=f))}}else v=we(v===a?v.splice(h,v.length):v),i?i(null,a,v,u):L.apply(a,v)})}function Ce(e){for(var t,n,i,o=e.length,a=r.relative[e[0].type],s=a||r.relative[" "],u=a?1:0,c=me(function(e){return e===t},s,!0),f=me(function(e){return O(t,e)>-1},s,!0),p=[function(e,n,r){var i=!a&&(r||n!==l)||((t=n).nodeType?c(e,n,r):f(e,n,r));return t=null,i}];u<o;u++)if(n=r.relative[e[u].type])p=[me(xe(p),n)];else{if((n=r.filter[e[u].type].apply(null,e[u].matches))[b]){for(i=++u;i<o;i++)if(r.relative[e[i].type])break;return Te(u>1&&xe(p),u>1&&ve(e.slice(0,u-1).concat({value:" "===e[u-2].type?"*":""})).replace(B,"$1"),n,u<i&&Ce(e.slice(u,i)),i<o&&Ce(e=e.slice(i)),i<o&&ve(e))}p.push(n)}return xe(p)}function Ee(e,t){var n=t.length>0,i=e.length>0,o=function(o,a,s,u,c){var f,h,y,v=0,m="0",x=o&&[],b=[],w=l,C=o||i&&r.find.TAG("*",c),E=T+=null==w?1:Math.random()||.1,k=C.length;for(c&&(l=a===d||a||c);m!==k&&null!=(f=C[m]);m++){if(i&&f){h=0,a||f.ownerDocument===d||(p(f),s=!g);while(y=e[h++])if(y(f,a||d,s)){u.push(f);break}c&&(T=E)}n&&((f=!y&&f)&&v--,o&&x.push(f))}if(v+=m,n&&m!==v){h=0;while(y=t[h++])y(x,b,a,s);if(o){if(v>0)while(m--)x[m]||b[m]||(b[m]=j.call(u));b=we(b)}L.apply(u,b),c&&!o&&b.length>0&&v+t.length>1&&oe.uniqueSort(u)}return c&&(T=E,l=w),x};return n?se(o):o}return s=oe.compile=function(e,t){var n,r=[],i=[],o=S[e+" "];if(!o){t||(t=a(e)),n=t.length;while(n--)(o=Ce(t[n]))[b]?r.push(o):i.push(o);(o=S(e,Ee(i,r))).selector=e}return o},u=oe.select=function(e,t,n,i){var o,u,l,c,f,p="function"==typeof e&&e,d=!i&&a(e=p.selector||e);if(n=n||[],1===d.length){if((u=d[0]=d[0].slice(0)).length>2&&"ID"===(l=u[0]).type&&9===t.nodeType&&g&&r.relative[u[1].type]){if(!(t=(r.find.ID(l.matches[0].replace(Z,ee),t)||[])[0]))return n;p&&(t=t.parentNode),e=e.slice(u.shift().value.length)}o=V.needsContext.test(e)?0:u.length;while(o--){if(l=u[o],r.relative[c=l.type])break;if((f=r.find[c])&&(i=f(l.matches[0].replace(Z,ee),K.test(u[0].type)&&ge(t.parentNode)||t))){if(u.splice(o,1),!(e=i.length&&ve(u)))return L.apply(n,i),n;break}}}return(p||s(e,d))(i,t,!g,n,!t||K.test(e)&&ge(t.parentNode)||t),n},n.sortStable=b.split("").sort(D).join("")===b,n.detectDuplicates=!!f,p(),n.sortDetached=ue(function(e){return 1&e.compareDocumentPosition(d.createElement("fieldset"))}),ue(function(e){return e.innerHTML="<a href='#'></a>","#"===e.firstChild.getAttribute("href")})||le("type|href|height|width",function(e,t,n){if(!n)return e.getAttribute(t,"type"===t.toLowerCase()?1:2)}),n.attributes&&ue(function(e){return e.innerHTML="<input/>",e.firstChild.setAttribute("value",""),""===e.firstChild.getAttribute("value")})||le("value",function(e,t,n){if(!n&&"input"===e.nodeName.toLowerCase())return e.defaultValue}),ue(function(e){return null==e.getAttribute("disabled")})||le(P,function(e,t,n){var r;if(!n)return!0===e[t]?t.toLowerCase():(r=e.getAttributeNode(t))&&r.specified?r.value:null}),oe}(e);w.find=E,w.expr=E.selectors,w.expr[":"]=w.expr.pseudos,w.uniqueSort=w.unique=E.uniqueSort,w.text=E.getText,w.isXMLDoc=E.isXML,w.contains=E.contains,w.escapeSelector=E.escape;var k=function(e,t,n){var r=[],i=void 0!==n;while((e=e[t])&&9!==e.nodeType)if(1===e.nodeType){if(i&&w(e).is(n))break;r.push(e)}return r},S=function(e,t){for(var n=[];e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n},D=w.expr.match.needsContext;function N(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()}var A=/^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function j(e,t,n){return g(t)?w.grep(e,function(e,r){return!!t.call(e,r,e)!==n}):t.nodeType?w.grep(e,function(e){return e===t!==n}):"string"!=typeof t?w.grep(e,function(e){return u.call(t,e)>-1!==n}):w.filter(t,e,n)}w.filter=function(e,t,n){var r=t[0];return n&&(e=":not("+e+")"),1===t.length&&1===r.nodeType?w.find.matchesSelector(r,e)?[r]:[]:w.find.matches(e,w.grep(t,function(e){return 1===e.nodeType}))},w.fn.extend({find:function(e){var t,n,r=this.length,i=this;if("string"!=typeof e)return this.pushStack(w(e).filter(function(){for(t=0;t<r;t++)if(w.contains(i[t],this))return!0}));for(n=this.pushStack([]),t=0;t<r;t++)w.find(e,i[t],n);return r>1?w.uniqueSort(n):n},filter:function(e){return this.pushStack(j(this,e||[],!1))},not:function(e){return this.pushStack(j(this,e||[],!0))},is:function(e){return!!j(this,"string"==typeof e&&D.test(e)?w(e):e||[],!1).length}});var q,L=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/;(w.fn.init=function(e,t,n){var i,o;if(!e)return this;if(n=n||q,"string"==typeof e){if(!(i="<"===e[0]&&">"===e[e.length-1]&&e.length>=3?[null,e,null]:L.exec(e))||!i[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(i[1]){if(t=t instanceof w?t[0]:t,w.merge(this,w.parseHTML(i[1],t&&t.nodeType?t.ownerDocument||t:r,!0)),A.test(i[1])&&w.isPlainObject(t))for(i in t)g(this[i])?this[i](t[i]):this.attr(i,t[i]);return this}return(o=r.getElementById(i[2]))&&(this[0]=o,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):g(e)?void 0!==n.ready?n.ready(e):e(w):w.makeArray(e,this)}).prototype=w.fn,q=w(r);var H=/^(?:parents|prev(?:Until|All))/,O={children:!0,contents:!0,next:!0,prev:!0};w.fn.extend({has:function(e){var t=w(e,this),n=t.length;return this.filter(function(){for(var e=0;e<n;e++)if(w.contains(this,t[e]))return!0})},closest:function(e,t){var n,r=0,i=this.length,o=[],a="string"!=typeof e&&w(e);if(!D.test(e))for(;r<i;r++)for(n=this[r];n&&n!==t;n=n.parentNode)if(n.nodeType<11&&(a?a.index(n)>-1:1===n.nodeType&&w.find.matchesSelector(n,e))){o.push(n);break}return this.pushStack(o.length>1?w.uniqueSort(o):o)},index:function(e){return e?"string"==typeof e?u.call(w(e),this[0]):u.call(this,e.jquery?e[0]:e):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){return this.pushStack(w.uniqueSort(w.merge(this.get(),w(e,t))))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}});function P(e,t){while((e=e[t])&&1!==e.nodeType);return e}w.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return k(e,"parentNode")},parentsUntil:function(e,t,n){return k(e,"parentNode",n)},next:function(e){return P(e,"nextSibling")},prev:function(e){return P(e,"previousSibling")},nextAll:function(e){return k(e,"nextSibling")},prevAll:function(e){return k(e,"previousSibling")},nextUntil:function(e,t,n){return k(e,"nextSibling",n)},prevUntil:function(e,t,n){return k(e,"previousSibling",n)},siblings:function(e){return S((e.parentNode||{}).firstChild,e)},children:function(e){return S(e.firstChild)},contents:function(e){return N(e,"iframe")?e.contentDocument:(N(e,"template")&&(e=e.content||e),w.merge([],e.childNodes))}},function(e,t){w.fn[e]=function(n,r){var i=w.map(this,t,n);return"Until"!==e.slice(-5)&&(r=n),r&&"string"==typeof r&&(i=w.filter(r,i)),this.length>1&&(O[e]||w.uniqueSort(i),H.test(e)&&i.reverse()),this.pushStack(i)}});var M=/[^\x20\t\r\n\f]+/g;function R(e){var t={};return w.each(e.match(M)||[],function(e,n){t[n]=!0}),t}w.Callbacks=function(e){e="string"==typeof e?R(e):w.extend({},e);var t,n,r,i,o=[],a=[],s=-1,u=function(){for(i=i||e.once,r=t=!0;a.length;s=-1){n=a.shift();while(++s<o.length)!1===o[s].apply(n[0],n[1])&&e.stopOnFalse&&(s=o.length,n=!1)}e.memory||(n=!1),t=!1,i&&(o=n?[]:"")},l={add:function(){return o&&(n&&!t&&(s=o.length-1,a.push(n)),function t(n){w.each(n,function(n,r){g(r)?e.unique&&l.has(r)||o.push(r):r&&r.length&&"string"!==x(r)&&t(r)})}(arguments),n&&!t&&u()),this},remove:function(){return w.each(arguments,function(e,t){var n;while((n=w.inArray(t,o,n))>-1)o.splice(n,1),n<=s&&s--}),this},has:function(e){return e?w.inArray(e,o)>-1:o.length>0},empty:function(){return o&&(o=[]),this},disable:function(){return i=a=[],o=n="",this},disabled:function(){return!o},lock:function(){return i=a=[],n||t||(o=n=""),this},locked:function(){return!!i},fireWith:function(e,n){return i||(n=[e,(n=n||[]).slice?n.slice():n],a.push(n),t||u()),this},fire:function(){return l.fireWith(this,arguments),this},fired:function(){return!!r}};return l};function I(e){return e}function W(e){throw e}function $(e,t,n,r){var i;try{e&&g(i=e.promise)?i.call(e).done(t).fail(n):e&&g(i=e.then)?i.call(e,t,n):t.apply(void 0,[e].slice(r))}catch(e){n.apply(void 0,[e])}}w.extend({Deferred:function(t){var n=[["notify","progress",w.Callbacks("memory"),w.Callbacks("memory"),2],["resolve","done",w.Callbacks("once memory"),w.Callbacks("once memory"),0,"resolved"],["reject","fail",w.Callbacks("once memory"),w.Callbacks("once memory"),1,"rejected"]],r="pending",i={state:function(){return r},always:function(){return o.done(arguments).fail(arguments),this},"catch":function(e){return i.then(null,e)},pipe:function(){var e=arguments;return w.Deferred(function(t){w.each(n,function(n,r){var i=g(e[r[4]])&&e[r[4]];o[r[1]](function(){var e=i&&i.apply(this,arguments);e&&g(e.promise)?e.promise().progress(t.notify).done(t.resolve).fail(t.reject):t[r[0]+"With"](this,i?[e]:arguments)})}),e=null}).promise()},then:function(t,r,i){var o=0;function a(t,n,r,i){return function(){var s=this,u=arguments,l=function(){var e,l;if(!(t<o)){if((e=r.apply(s,u))===n.promise())throw new TypeError("Thenable self-resolution");l=e&&("object"==typeof e||"function"==typeof e)&&e.then,g(l)?i?l.call(e,a(o,n,I,i),a(o,n,W,i)):(o++,l.call(e,a(o,n,I,i),a(o,n,W,i),a(o,n,I,n.notifyWith))):(r!==I&&(s=void 0,u=[e]),(i||n.resolveWith)(s,u))}},c=i?l:function(){try{l()}catch(e){w.Deferred.exceptionHook&&w.Deferred.exceptionHook(e,c.stackTrace),t+1>=o&&(r!==W&&(s=void 0,u=[e]),n.rejectWith(s,u))}};t?c():(w.Deferred.getStackHook&&(c.stackTrace=w.Deferred.getStackHook()),e.setTimeout(c))}}return w.Deferred(function(e){n[0][3].add(a(0,e,g(i)?i:I,e.notifyWith)),n[1][3].add(a(0,e,g(t)?t:I)),n[2][3].add(a(0,e,g(r)?r:W))}).promise()},promise:function(e){return null!=e?w.extend(e,i):i}},o={};return w.each(n,function(e,t){var a=t[2],s=t[5];i[t[1]]=a.add,s&&a.add(function(){r=s},n[3-e][2].disable,n[3-e][3].disable,n[0][2].lock,n[0][3].lock),a.add(t[3].fire),o[t[0]]=function(){return o[t[0]+"With"](this===o?void 0:this,arguments),this},o[t[0]+"With"]=a.fireWith}),i.promise(o),t&&t.call(o,o),o},when:function(e){var t=arguments.length,n=t,r=Array(n),i=o.call(arguments),a=w.Deferred(),s=function(e){return function(n){r[e]=this,i[e]=arguments.length>1?o.call(arguments):n,--t||a.resolveWith(r,i)}};if(t<=1&&($(e,a.done(s(n)).resolve,a.reject,!t),"pending"===a.state()||g(i[n]&&i[n].then)))return a.then();while(n--)$(i[n],s(n),a.reject);return a.promise()}});var B=/^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;w.Deferred.exceptionHook=function(t,n){e.console&&e.console.warn&&t&&B.test(t.name)&&e.console.warn("jQuery.Deferred exception: "+t.message,t.stack,n)},w.readyException=function(t){e.setTimeout(function(){throw t})};var F=w.Deferred();w.fn.ready=function(e){return F.then(e)["catch"](function(e){w.readyException(e)}),this},w.extend({isReady:!1,readyWait:1,ready:function(e){(!0===e?--w.readyWait:w.isReady)||(w.isReady=!0,!0!==e&&--w.readyWait>0||F.resolveWith(r,[w]))}}),w.ready.then=F.then;function _(){r.removeEventListener("DOMContentLoaded",_),e.removeEventListener("load",_),w.ready()}"complete"===r.readyState||"loading"!==r.readyState&&!r.documentElement.doScroll?e.setTimeout(w.ready):(r.addEventListener("DOMContentLoaded",_),e.addEventListener("load",_));var z=function(e,t,n,r,i,o,a){var s=0,u=e.length,l=null==n;if("object"===x(n)){i=!0;for(s in n)z(e,t,s,n[s],!0,o,a)}else if(void 0!==r&&(i=!0,g(r)||(a=!0),l&&(a?(t.call(e,r),t=null):(l=t,t=function(e,t,n){return l.call(w(e),n)})),t))for(;s<u;s++)t(e[s],n,a?r:r.call(e[s],s,t(e[s],n)));return i?e:l?t.call(e):u?t(e[0],n):o},X=/^-ms-/,U=/-([a-z])/g;function V(e,t){return t.toUpperCase()}function G(e){return e.replace(X,"ms-").replace(U,V)}var Y=function(e){return 1===e.nodeType||9===e.nodeType||!+e.nodeType};function Q(){this.expando=w.expando+Q.uid++}Q.uid=1,Q.prototype={cache:function(e){var t=e[this.expando];return t||(t={},Y(e)&&(e.nodeType?e[this.expando]=t:Object.defineProperty(e,this.expando,{value:t,configurable:!0}))),t},set:function(e,t,n){var r,i=this.cache(e);if("string"==typeof t)i[G(t)]=n;else for(r in t)i[G(r)]=t[r];return i},get:function(e,t){return void 0===t?this.cache(e):e[this.expando]&&e[this.expando][G(t)]},access:function(e,t,n){return void 0===t||t&&"string"==typeof t&&void 0===n?this.get(e,t):(this.set(e,t,n),void 0!==n?n:t)},remove:function(e,t){var n,r=e[this.expando];if(void 0!==r){if(void 0!==t){n=(t=Array.isArray(t)?t.map(G):(t=G(t))in r?[t]:t.match(M)||[]).length;while(n--)delete r[t[n]]}(void 0===t||w.isEmptyObject(r))&&(e.nodeType?e[this.expando]=void 0:delete e[this.expando])}},hasData:function(e){var t=e[this.expando];return void 0!==t&&!w.isEmptyObject(t)}};var J=new Q,K=new Q,Z=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,ee=/[A-Z]/g;function te(e){return"true"===e||"false"!==e&&("null"===e?null:e===+e+""?+e:Z.test(e)?JSON.parse(e):e)}function ne(e,t,n){var r;if(void 0===n&&1===e.nodeType)if(r="data-"+t.replace(ee,"-$&").toLowerCase(),"string"==typeof(n=e.getAttribute(r))){try{n=te(n)}catch(e){}K.set(e,t,n)}else n=void 0;return n}w.extend({hasData:function(e){return K.hasData(e)||J.hasData(e)},data:function(e,t,n){return K.access(e,t,n)},removeData:function(e,t){K.remove(e,t)},_data:function(e,t,n){return J.access(e,t,n)},_removeData:function(e,t){J.remove(e,t)}}),w.fn.extend({data:function(e,t){var n,r,i,o=this[0],a=o&&o.attributes;if(void 0===e){if(this.length&&(i=K.get(o),1===o.nodeType&&!J.get(o,"hasDataAttrs"))){n=a.length;while(n--)a[n]&&0===(r=a[n].name).indexOf("data-")&&(r=G(r.slice(5)),ne(o,r,i[r]));J.set(o,"hasDataAttrs",!0)}return i}return"object"==typeof e?this.each(function(){K.set(this,e)}):z(this,function(t){var n;if(o&&void 0===t){if(void 0!==(n=K.get(o,e)))return n;if(void 0!==(n=ne(o,e)))return n}else this.each(function(){K.set(this,e,t)})},null,t,arguments.length>1,null,!0)},removeData:function(e){return this.each(function(){K.remove(this,e)})}}),w.extend({queue:function(e,t,n){var r;if(e)return t=(t||"fx")+"queue",r=J.get(e,t),n&&(!r||Array.isArray(n)?r=J.access(e,t,w.makeArray(n)):r.push(n)),r||[]},dequeue:function(e,t){t=t||"fx";var n=w.queue(e,t),r=n.length,i=n.shift(),o=w._queueHooks(e,t),a=function(){w.dequeue(e,t)};"inprogress"===i&&(i=n.shift(),r--),i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,a,o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return J.get(e,n)||J.access(e,n,{empty:w.Callbacks("once memory").add(function(){J.remove(e,[t+"queue",n])})})}}),w.fn.extend({queue:function(e,t){var n=2;return"string"!=typeof e&&(t=e,e="fx",n--),arguments.length<n?w.queue(this[0],e):void 0===t?this:this.each(function(){var n=w.queue(this,e,t);w._queueHooks(this,e),"fx"===e&&"inprogress"!==n[0]&&w.dequeue(this,e)})},dequeue:function(e){return this.each(function(){w.dequeue(this,e)})},clearQueue:function(e){return this.queue(e||"fx",[])},promise:function(e,t){var n,r=1,i=w.Deferred(),o=this,a=this.length,s=function(){--r||i.resolveWith(o,[o])};"string"!=typeof e&&(t=e,e=void 0),e=e||"fx";while(a--)(n=J.get(o[a],e+"queueHooks"))&&n.empty&&(r++,n.empty.add(s));return s(),i.promise(t)}});var re=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,ie=new RegExp("^(?:([+-])=|)("+re+")([a-z%]*)$","i"),oe=["Top","Right","Bottom","Left"],ae=function(e,t){return"none"===(e=t||e).style.display||""===e.style.display&&w.contains(e.ownerDocument,e)&&"none"===w.css(e,"display")},se=function(e,t,n,r){var i,o,a={};for(o in t)a[o]=e.style[o],e.style[o]=t[o];i=n.apply(e,r||[]);for(o in t)e.style[o]=a[o];return i};function ue(e,t,n,r){var i,o,a=20,s=r?function(){return r.cur()}:function(){return w.css(e,t,"")},u=s(),l=n&&n[3]||(w.cssNumber[t]?"":"px"),c=(w.cssNumber[t]||"px"!==l&&+u)&&ie.exec(w.css(e,t));if(c&&c[3]!==l){u/=2,l=l||c[3],c=+u||1;while(a--)w.style(e,t,c+l),(1-o)*(1-(o=s()/u||.5))<=0&&(a=0),c/=o;c*=2,w.style(e,t,c+l),n=n||[]}return n&&(c=+c||+u||0,i=n[1]?c+(n[1]+1)*n[2]:+n[2],r&&(r.unit=l,r.start=c,r.end=i)),i}var le={};function ce(e){var t,n=e.ownerDocument,r=e.nodeName,i=le[r];return i||(t=n.body.appendChild(n.createElement(r)),i=w.css(t,"display"),t.parentNode.removeChild(t),"none"===i&&(i="block"),le[r]=i,i)}function fe(e,t){for(var n,r,i=[],o=0,a=e.length;o<a;o++)(r=e[o]).style&&(n=r.style.display,t?("none"===n&&(i[o]=J.get(r,"display")||null,i[o]||(r.style.display="")),""===r.style.display&&ae(r)&&(i[o]=ce(r))):"none"!==n&&(i[o]="none",J.set(r,"display",n)));for(o=0;o<a;o++)null!=i[o]&&(e[o].style.display=i[o]);return e}w.fn.extend({show:function(){return fe(this,!0)},hide:function(){return fe(this)},toggle:function(e){return"boolean"==typeof e?e?this.show():this.hide():this.each(function(){ae(this)?w(this).show():w(this).hide()})}});var pe=/^(?:checkbox|radio)$/i,de=/<([a-z][^\/\0>\x20\t\r\n\f]+)/i,he=/^$|^module$|\/(?:java|ecma)script/i,ge={option:[1,"<select multiple='multiple'>","</select>"],thead:[1,"<table>","</table>"],col:[2,"<table><colgroup>","</colgroup></table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:[0,"",""]};ge.optgroup=ge.option,ge.tbody=ge.tfoot=ge.colgroup=ge.caption=ge.thead,ge.th=ge.td;function ye(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&N(e,t)?w.merge([e],n):n}function ve(e,t){for(var n=0,r=e.length;n<r;n++)J.set(e[n],"globalEval",!t||J.get(t[n],"globalEval"))}var me=/<|&#?\w+;/;function xe(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d<h;d++)if((o=e[d])||0===o)if("object"===x(o))w.merge(p,o.nodeType?[o]:o);else if(me.test(o)){a=a||f.appendChild(t.createElement("div")),s=(de.exec(o)||["",""])[1].toLowerCase(),u=ge[s]||ge._default,a.innerHTML=u[1]+w.htmlPrefilter(o)+u[2],c=u[0];while(c--)a=a.lastChild;w.merge(p,a.childNodes),(a=f.firstChild).textContent=""}else p.push(t.createTextNode(o));f.textContent="",d=0;while(o=p[d++])if(r&&w.inArray(o,r)>-1)i&&i.push(o);else if(l=w.contains(o.ownerDocument,o),a=ye(f.appendChild(o),"script"),l&&ve(a),n){c=0;while(o=a[c++])he.test(o.type||"")&&n.push(o)}return f}!function(){var e=r.createDocumentFragment().appendChild(r.createElement("div")),t=r.createElement("input");t.setAttribute("type","radio"),t.setAttribute("checked","checked"),t.setAttribute("name","t"),e.appendChild(t),h.checkClone=e.cloneNode(!0).cloneNode(!0).lastChild.checked,e.innerHTML="<textarea>x</textarea>",h.noCloneChecked=!!e.cloneNode(!0).lastChild.defaultValue}();var be=r.documentElement,we=/^key/,Te=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,Ce=/^([^.]*)(?:\.(.+)|)/;function Ee(){return!0}function ke(){return!1}function Se(){try{return r.activeElement}catch(e){}}function De(e,t,n,r,i,o){var a,s;if("object"==typeof t){"string"!=typeof n&&(r=r||n,n=void 0);for(s in t)De(e,s,n,r,t[s],o);return e}if(null==r&&null==i?(i=n,r=n=void 0):null==i&&("string"==typeof n?(i=r,r=void 0):(i=r,r=n,n=void 0)),!1===i)i=ke;else if(!i)return e;return 1===o&&(a=i,(i=function(e){return w().off(e),a.apply(this,arguments)}).guid=a.guid||(a.guid=w.guid++)),e.each(function(){w.event.add(this,t,i,r,n)})}w.event={global:{},add:function(e,t,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,y=J.get(e);if(y){n.handler&&(n=(o=n).handler,i=o.selector),i&&w.find.matchesSelector(be,i),n.guid||(n.guid=w.guid++),(u=y.events)||(u=y.events={}),(a=y.handle)||(a=y.handle=function(t){return"undefined"!=typeof w&&w.event.triggered!==t.type?w.event.dispatch.apply(e,arguments):void 0}),l=(t=(t||"").match(M)||[""]).length;while(l--)d=g=(s=Ce.exec(t[l])||[])[1],h=(s[2]||"").split(".").sort(),d&&(f=w.event.special[d]||{},d=(i?f.delegateType:f.bindType)||d,f=w.event.special[d]||{},c=w.extend({type:d,origType:g,data:r,handler:n,guid:n.guid,selector:i,needsContext:i&&w.expr.match.needsContext.test(i),namespace:h.join(".")},o),(p=u[d])||((p=u[d]=[]).delegateCount=0,f.setup&&!1!==f.setup.call(e,r,h,a)||e.addEventListener&&e.addEventListener(d,a)),f.add&&(f.add.call(e,c),c.handler.guid||(c.handler.guid=n.guid)),i?p.splice(p.delegateCount++,0,c):p.push(c),w.event.global[d]=!0)}},remove:function(e,t,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,y=J.hasData(e)&&J.get(e);if(y&&(u=y.events)){l=(t=(t||"").match(M)||[""]).length;while(l--)if(s=Ce.exec(t[l])||[],d=g=s[1],h=(s[2]||"").split(".").sort(),d){f=w.event.special[d]||{},p=u[d=(r?f.delegateType:f.bindType)||d]||[],s=s[2]&&new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),a=o=p.length;while(o--)c=p[o],!i&&g!==c.origType||n&&n.guid!==c.guid||s&&!s.test(c.namespace)||r&&r!==c.selector&&("**"!==r||!c.selector)||(p.splice(o,1),c.selector&&p.delegateCount--,f.remove&&f.remove.call(e,c));a&&!p.length&&(f.teardown&&!1!==f.teardown.call(e,h,y.handle)||w.removeEvent(e,d,y.handle),delete u[d])}else for(d in u)w.event.remove(e,d+t[l],n,r,!0);w.isEmptyObject(u)&&J.remove(e,"handle events")}},dispatch:function(e){var t=w.event.fix(e),n,r,i,o,a,s,u=new Array(arguments.length),l=(J.get(this,"events")||{})[t.type]||[],c=w.event.special[t.type]||{};for(u[0]=t,n=1;n<arguments.length;n++)u[n]=arguments[n];if(t.delegateTarget=this,!c.preDispatch||!1!==c.preDispatch.call(this,t)){s=w.event.handlers.call(this,t,l),n=0;while((o=s[n++])&&!t.isPropagationStopped()){t.currentTarget=o.elem,r=0;while((a=o.handlers[r++])&&!t.isImmediatePropagationStopped())t.rnamespace&&!t.rnamespace.test(a.namespace)||(t.handleObj=a,t.data=a.data,void 0!==(i=((w.event.special[a.origType]||{}).handle||a.handler).apply(o.elem,u))&&!1===(t.result=i)&&(t.preventDefault(),t.stopPropagation()))}return c.postDispatch&&c.postDispatch.call(this,t),t.result}},handlers:function(e,t){var n,r,i,o,a,s=[],u=t.delegateCount,l=e.target;if(u&&l.nodeType&&!("click"===e.type&&e.button>=1))for(;l!==this;l=l.parentNode||this)if(1===l.nodeType&&("click"!==e.type||!0!==l.disabled)){for(o=[],a={},n=0;n<u;n++)void 0===a[i=(r=t[n]).selector+" "]&&(a[i]=r.needsContext?w(i,this).index(l)>-1:w.find(i,this,null,[l]).length),a[i]&&o.push(r);o.length&&s.push({elem:l,handlers:o})}return l=this,u<t.length&&s.push({elem:l,handlers:t.slice(u)}),s},addProp:function(e,t){Object.defineProperty(w.Event.prototype,e,{enumerable:!0,configurable:!0,get:g(t)?function(){if(this.originalEvent)return t(this.originalEvent)}:function(){if(this.originalEvent)return this.originalEvent[e]},set:function(t){Object.defineProperty(this,e,{enumerable:!0,configurable:!0,writable:!0,value:t})}})},fix:function(e){return e[w.expando]?e:new w.Event(e)},special:{load:{noBubble:!0},focus:{trigger:function(){if(this!==Se()&&this.focus)return this.focus(),!1},delegateType:"focusin"},blur:{trigger:function(){if(this===Se()&&this.blur)return this.blur(),!1},delegateType:"focusout"},click:{trigger:function(){if("checkbox"===this.type&&this.click&&N(this,"input"))return this.click(),!1},_default:function(e){return N(e.target,"a")}},beforeunload:{postDispatch:function(e){void 0!==e.result&&e.originalEvent&&(e.originalEvent.returnValue=e.result)}}}},w.removeEvent=function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n)},w.Event=function(e,t){if(!(this instanceof w.Event))return new w.Event(e,t);e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||void 0===e.defaultPrevented&&!1===e.returnValue?Ee:ke,this.target=e.target&&3===e.target.nodeType?e.target.parentNode:e.target,this.currentTarget=e.currentTarget,this.relatedTarget=e.relatedTarget):this.type=e,t&&w.extend(this,t),this.timeStamp=e&&e.timeStamp||Date.now(),this[w.expando]=!0},w.Event.prototype={constructor:w.Event,isDefaultPrevented:ke,isPropagationStopped:ke,isImmediatePropagationStopped:ke,isSimulated:!1,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=Ee,e&&!this.isSimulated&&e.preventDefault()},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=Ee,e&&!this.isSimulated&&e.stopPropagation()},stopImmediatePropagation:function(){var e=this.originalEvent;this.isImmediatePropagationStopped=Ee,e&&!this.isSimulated&&e.stopImmediatePropagation(),this.stopPropagation()}},w.each({altKey:!0,bubbles:!0,cancelable:!0,changedTouches:!0,ctrlKey:!0,detail:!0,eventPhase:!0,metaKey:!0,pageX:!0,pageY:!0,shiftKey:!0,view:!0,"char":!0,charCode:!0,key:!0,keyCode:!0,button:!0,buttons:!0,clientX:!0,clientY:!0,offsetX:!0,offsetY:!0,pointerId:!0,pointerType:!0,screenX:!0,screenY:!0,targetTouches:!0,toElement:!0,touches:!0,which:function(e){var t=e.button;return null==e.which&&we.test(e.type)?null!=e.charCode?e.charCode:e.keyCode:!e.which&&void 0!==t&&Te.test(e.type)?1&t?1:2&t?3:4&t?2:0:e.which}},w.event.addProp),w.each({mouseenter:"mouseover",mouseleave:"mouseout",pointerenter:"pointerover",pointerleave:"pointerout"},function(e,t){w.event.special[e]={delegateType:t,bindType:t,handle:function(e){var n,r=this,i=e.relatedTarget,o=e.handleObj;return i&&(i===r||w.contains(r,i))||(e.type=o.origType,n=o.handler.apply(this,arguments),e.type=t),n}}}),w.fn.extend({on:function(e,t,n,r){return De(this,e,t,n,r)},one:function(e,t,n,r){return De(this,e,t,n,r,1)},off:function(e,t,n){var r,i;if(e&&e.preventDefault&&e.handleObj)return r=e.handleObj,w(e.delegateTarget).off(r.namespace?r.origType+"."+r.namespace:r.origType,r.selector,r.handler),this;if("object"==typeof e){for(i in e)this.off(i,t,e[i]);return this}return!1!==t&&"function"!=typeof t||(n=t,t=void 0),!1===n&&(n=ke),this.each(function(){w.event.remove(this,e,n,t)})}});var Ne=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([a-z][^\/\0>\x20\t\r\n\f]*)[^>]*)\/>/gi,Ae=/<script|<style|<link/i,je=/checked\s*(?:[^=]|=\s*.checked.)/i,qe=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g;function Le(e,t){return N(e,"table")&&N(11!==t.nodeType?t:t.firstChild,"tr")?w(e).children("tbody")[0]||e:e}function He(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function Oe(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Pe(e,t){var n,r,i,o,a,s,u,l;if(1===t.nodeType){if(J.hasData(e)&&(o=J.access(e),a=J.set(t,o),l=o.events)){delete a.handle,a.events={};for(i in l)for(n=0,r=l[i].length;n<r;n++)w.event.add(t,i,l[i][n])}K.hasData(e)&&(s=K.access(e),u=w.extend({},s),K.set(t,u))}}function Me(e,t){var n=t.nodeName.toLowerCase();"input"===n&&pe.test(e.type)?t.checked=e.checked:"input"!==n&&"textarea"!==n||(t.defaultValue=e.defaultValue)}function Re(e,t,n,r){t=a.apply([],t);var i,o,s,u,l,c,f=0,p=e.length,d=p-1,y=t[0],v=g(y);if(v||p>1&&"string"==typeof y&&!h.checkClone&&je.test(y))return e.each(function(i){var o=e.eq(i);v&&(t[0]=y.call(this,i,o.html())),Re(o,t,n,r)});if(p&&(i=xe(t,e[0].ownerDocument,!1,e,r),o=i.firstChild,1===i.childNodes.length&&(i=o),o||r)){for(u=(s=w.map(ye(i,"script"),He)).length;f<p;f++)l=i,f!==d&&(l=w.clone(l,!0,!0),u&&w.merge(s,ye(l,"script"))),n.call(e[f],l,f);if(u)for(c=s[s.length-1].ownerDocument,w.map(s,Oe),f=0;f<u;f++)l=s[f],he.test(l.type||"")&&!J.access(l,"globalEval")&&w.contains(c,l)&&(l.src&&"module"!==(l.type||"").toLowerCase()?w._evalUrl&&w._evalUrl(l.src):m(l.textContent.replace(qe,""),c,l))}return e}function Ie(e,t,n){for(var r,i=t?w.filter(t,e):e,o=0;null!=(r=i[o]);o++)n||1!==r.nodeType||w.cleanData(ye(r)),r.parentNode&&(n&&w.contains(r.ownerDocument,r)&&ve(ye(r,"script")),r.parentNode.removeChild(r));return e}w.extend({htmlPrefilter:function(e){return e.replace(Ne,"<$1></$2>")},clone:function(e,t,n){var r,i,o,a,s=e.cloneNode(!0),u=w.contains(e.ownerDocument,e);if(!(h.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||w.isXMLDoc(e)))for(a=ye(s),r=0,i=(o=ye(e)).length;r<i;r++)Me(o[r],a[r]);if(t)if(n)for(o=o||ye(e),a=a||ye(s),r=0,i=o.length;r<i;r++)Pe(o[r],a[r]);else Pe(e,s);return(a=ye(s,"script")).length>0&&ve(a,!u&&ye(e,"script")),s},cleanData:function(e){for(var t,n,r,i=w.event.special,o=0;void 0!==(n=e[o]);o++)if(Y(n)){if(t=n[J.expando]){if(t.events)for(r in t.events)i[r]?w.event.remove(n,r):w.removeEvent(n,r,t.handle);n[J.expando]=void 0}n[K.expando]&&(n[K.expando]=void 0)}}}),w.fn.extend({detach:function(e){return Ie(this,e,!0)},remove:function(e){return Ie(this,e)},text:function(e){return z(this,function(e){return void 0===e?w.text(this):this.empty().each(function(){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(this.textContent=e)})},null,e,arguments.length)},append:function(){return Re(this,arguments,function(e){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||Le(this,e).appendChild(e)})},prepend:function(){return Re(this,arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=Le(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return Re(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return Re(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},empty:function(){for(var e,t=0;null!=(e=this[t]);t++)1===e.nodeType&&(w.cleanData(ye(e,!1)),e.textContent="");return this},clone:function(e,t){return e=null!=e&&e,t=null==t?e:t,this.map(function(){return w.clone(this,e,t)})},html:function(e){return z(this,function(e){var t=this[0]||{},n=0,r=this.length;if(void 0===e&&1===t.nodeType)return t.innerHTML;if("string"==typeof e&&!Ae.test(e)&&!ge[(de.exec(e)||["",""])[1].toLowerCase()]){e=w.htmlPrefilter(e);try{for(;n<r;n++)1===(t=this[n]||{}).nodeType&&(w.cleanData(ye(t,!1)),t.innerHTML=e);t=0}catch(e){}}t&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(){var e=[];return Re(this,arguments,function(t){var n=this.parentNode;w.inArray(this,e)<0&&(w.cleanData(ye(this)),n&&n.replaceChild(t,this))},e)}}),w.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,t){w.fn[e]=function(e){for(var n,r=[],i=w(e),o=i.length-1,a=0;a<=o;a++)n=a===o?this:this.clone(!0),w(i[a])[t](n),s.apply(r,n.get());return this.pushStack(r)}});var We=new RegExp("^("+re+")(?!px)[a-z%]+$","i"),$e=function(t){var n=t.ownerDocument.defaultView;return n&&n.opener||(n=e),n.getComputedStyle(t)},Be=new RegExp(oe.join("|"),"i");!function(){function t(){if(c){l.style.cssText="position:absolute;left:-11111px;width:60px;margin-top:1px;padding:0;border:0",c.style.cssText="position:relative;display:block;box-sizing:border-box;overflow:scroll;margin:auto;border:1px;padding:1px;width:60%;top:1%",be.appendChild(l).appendChild(c);var t=e.getComputedStyle(c);i="1%"!==t.top,u=12===n(t.marginLeft),c.style.right="60%",s=36===n(t.right),o=36===n(t.width),c.style.position="absolute",a=36===c.offsetWidth||"absolute",be.removeChild(l),c=null}}function n(e){return Math.round(parseFloat(e))}var i,o,a,s,u,l=r.createElement("div"),c=r.createElement("div");c.style&&(c.style.backgroundClip="content-box",c.cloneNode(!0).style.backgroundClip="",h.clearCloneStyle="content-box"===c.style.backgroundClip,w.extend(h,{boxSizingReliable:function(){return t(),o},pixelBoxStyles:function(){return t(),s},pixelPosition:function(){return t(),i},reliableMarginLeft:function(){return t(),u},scrollboxSize:function(){return t(),a}}))}();function Fe(e,t,n){var r,i,o,a,s=e.style;return(n=n||$e(e))&&(""!==(a=n.getPropertyValue(t)||n[t])||w.contains(e.ownerDocument,e)||(a=w.style(e,t)),!h.pixelBoxStyles()&&We.test(a)&&Be.test(t)&&(r=s.width,i=s.minWidth,o=s.maxWidth,s.minWidth=s.maxWidth=s.width=a,a=n.width,s.width=r,s.minWidth=i,s.maxWidth=o)),void 0!==a?a+"":a}function _e(e,t){return{get:function(){if(!e())return(this.get=t).apply(this,arguments);delete this.get}}}var ze=/^(none|table(?!-c[ea]).+)/,Xe=/^--/,Ue={position:"absolute",visibility:"hidden",display:"block"},Ve={letterSpacing:"0",fontWeight:"400"},Ge=["Webkit","Moz","ms"],Ye=r.createElement("div").style;function Qe(e){if(e in Ye)return e;var t=e[0].toUpperCase()+e.slice(1),n=Ge.length;while(n--)if((e=Ge[n]+t)in Ye)return e}function Je(e){var t=w.cssProps[e];return t||(t=w.cssProps[e]=Qe(e)||e),t}function Ke(e,t,n){var r=ie.exec(t);return r?Math.max(0,r[2]-(n||0))+(r[3]||"px"):t}function Ze(e,t,n,r,i,o){var a="width"===t?1:0,s=0,u=0;if(n===(r?"border":"content"))return 0;for(;a<4;a+=2)"margin"===n&&(u+=w.css(e,n+oe[a],!0,i)),r?("content"===n&&(u-=w.css(e,"padding"+oe[a],!0,i)),"margin"!==n&&(u-=w.css(e,"border"+oe[a]+"Width",!0,i))):(u+=w.css(e,"padding"+oe[a],!0,i),"padding"!==n?u+=w.css(e,"border"+oe[a]+"Width",!0,i):s+=w.css(e,"border"+oe[a]+"Width",!0,i));return!r&&o>=0&&(u+=Math.max(0,Math.ceil(e["offset"+t[0].toUpperCase()+t.slice(1)]-o-u-s-.5))),u}function et(e,t,n){var r=$e(e),i=Fe(e,t,r),o="border-box"===w.css(e,"boxSizing",!1,r),a=o;if(We.test(i)){if(!n)return i;i="auto"}return a=a&&(h.boxSizingReliable()||i===e.style[t]),("auto"===i||!parseFloat(i)&&"inline"===w.css(e,"display",!1,r))&&(i=e["offset"+t[0].toUpperCase()+t.slice(1)],a=!0),(i=parseFloat(i)||0)+Ze(e,t,n||(o?"border":"content"),a,r,i)+"px"}w.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=Fe(e,"opacity");return""===n?"1":n}}}},cssNumber:{animationIterationCount:!0,columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{},style:function(e,t,n,r){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var i,o,a,s=G(t),u=Xe.test(t),l=e.style;if(u||(t=Je(s)),a=w.cssHooks[t]||w.cssHooks[s],void 0===n)return a&&"get"in a&&void 0!==(i=a.get(e,!1,r))?i:l[t];"string"==(o=typeof n)&&(i=ie.exec(n))&&i[1]&&(n=ue(e,t,i),o="number"),null!=n&&n===n&&("number"===o&&(n+=i&&i[3]||(w.cssNumber[s]?"":"px")),h.clearCloneStyle||""!==n||0!==t.indexOf("background")||(l[t]="inherit"),a&&"set"in a&&void 0===(n=a.set(e,n,r))||(u?l.setProperty(t,n):l[t]=n))}},css:function(e,t,n,r){var i,o,a,s=G(t);return Xe.test(t)||(t=Je(s)),(a=w.cssHooks[t]||w.cssHooks[s])&&"get"in a&&(i=a.get(e,!0,n)),void 0===i&&(i=Fe(e,t,r)),"normal"===i&&t in Ve&&(i=Ve[t]),""===n||n?(o=parseFloat(i),!0===n||isFinite(o)?o||0:i):i}}),w.each(["height","width"],function(e,t){w.cssHooks[t]={get:function(e,n,r){if(n)return!ze.test(w.css(e,"display"))||e.getClientRects().length&&e.getBoundingClientRect().width?et(e,t,r):se(e,Ue,function(){return et(e,t,r)})},set:function(e,n,r){var i,o=$e(e),a="border-box"===w.css(e,"boxSizing",!1,o),s=r&&Ze(e,t,r,a,o);return a&&h.scrollboxSize()===o.position&&(s-=Math.ceil(e["offset"+t[0].toUpperCase()+t.slice(1)]-parseFloat(o[t])-Ze(e,t,"border",!1,o)-.5)),s&&(i=ie.exec(n))&&"px"!==(i[3]||"px")&&(e.style[t]=n,n=w.css(e,t)),Ke(e,n,s)}}}),w.cssHooks.marginLeft=_e(h.reliableMarginLeft,function(e,t){if(t)return(parseFloat(Fe(e,"marginLeft"))||e.getBoundingClientRect().left-se(e,{marginLeft:0},function(){return e.getBoundingClientRect().left}))+"px"}),w.each({margin:"",padding:"",border:"Width"},function(e,t){w.cssHooks[e+t]={expand:function(n){for(var r=0,i={},o="string"==typeof n?n.split(" "):[n];r<4;r++)i[e+oe[r]+t]=o[r]||o[r-2]||o[0];return i}},"margin"!==e&&(w.cssHooks[e+t].set=Ke)}),w.fn.extend({css:function(e,t){return z(this,function(e,t,n){var r,i,o={},a=0;if(Array.isArray(t)){for(r=$e(e),i=t.length;a<i;a++)o[t[a]]=w.css(e,t[a],!1,r);return o}return void 0!==n?w.style(e,t,n):w.css(e,t)},e,t,arguments.length>1)}});function tt(e,t,n,r,i){return new tt.prototype.init(e,t,n,r,i)}w.Tween=tt,tt.prototype={constructor:tt,init:function(e,t,n,r,i,o){this.elem=e,this.prop=n,this.easing=i||w.easing._default,this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=o||(w.cssNumber[n]?"":"px")},cur:function(){var e=tt.propHooks[this.prop];return e&&e.get?e.get(this):tt.propHooks._default.get(this)},run:function(e){var t,n=tt.propHooks[this.prop];return this.options.duration?this.pos=t=w.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):this.pos=t=e,this.now=(this.end-this.start)*t+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):tt.propHooks._default.set(this),this}},tt.prototype.init.prototype=tt.prototype,tt.propHooks={_default:{get:function(e){var t;return 1!==e.elem.nodeType||null!=e.elem[e.prop]&&null==e.elem.style[e.prop]?e.elem[e.prop]:(t=w.css(e.elem,e.prop,""))&&"auto"!==t?t:0},set:function(e){w.fx.step[e.prop]?w.fx.step[e.prop](e):1!==e.elem.nodeType||null==e.elem.style[w.cssProps[e.prop]]&&!w.cssHooks[e.prop]?e.elem[e.prop]=e.now:w.style(e.elem,e.prop,e.now+e.unit)}}},tt.propHooks.scrollTop=tt.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},w.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2},_default:"swing"},w.fx=tt.prototype.init,w.fx.step={};var nt,rt,it=/^(?:toggle|show|hide)$/,ot=/queueHooks$/;function at(){rt&&(!1===r.hidden&&e.requestAnimationFrame?e.requestAnimationFrame(at):e.setTimeout(at,w.fx.interval),w.fx.tick())}function st(){return e.setTimeout(function(){nt=void 0}),nt=Date.now()}function ut(e,t){var n,r=0,i={height:e};for(t=t?1:0;r<4;r+=2-t)i["margin"+(n=oe[r])]=i["padding"+n]=e;return t&&(i.opacity=i.width=e),i}function lt(e,t,n){for(var r,i=(pt.tweeners[t]||[]).concat(pt.tweeners["*"]),o=0,a=i.length;o<a;o++)if(r=i[o].call(n,t,e))return r}function ct(e,t,n){var r,i,o,a,s,u,l,c,f="width"in t||"height"in t,p=this,d={},h=e.style,g=e.nodeType&&ae(e),y=J.get(e,"fxshow");n.queue||(null==(a=w._queueHooks(e,"fx")).unqueued&&(a.unqueued=0,s=a.empty.fire,a.empty.fire=function(){a.unqueued||s()}),a.unqueued++,p.always(function(){p.always(function(){a.unqueued--,w.queue(e,"fx").length||a.empty.fire()})}));for(r in t)if(i=t[r],it.test(i)){if(delete t[r],o=o||"toggle"===i,i===(g?"hide":"show")){if("show"!==i||!y||void 0===y[r])continue;g=!0}d[r]=y&&y[r]||w.style(e,r)}if((u=!w.isEmptyObject(t))||!w.isEmptyObject(d)){f&&1===e.nodeType&&(n.overflow=[h.overflow,h.overflowX,h.overflowY],null==(l=y&&y.display)&&(l=J.get(e,"display")),"none"===(c=w.css(e,"display"))&&(l?c=l:(fe([e],!0),l=e.style.display||l,c=w.css(e,"display"),fe([e]))),("inline"===c||"inline-block"===c&&null!=l)&&"none"===w.css(e,"float")&&(u||(p.done(function(){h.display=l}),null==l&&(c=h.display,l="none"===c?"":c)),h.display="inline-block")),n.overflow&&(h.overflow="hidden",p.always(function(){h.overflow=n.overflow[0],h.overflowX=n.overflow[1],h.overflowY=n.overflow[2]})),u=!1;for(r in d)u||(y?"hidden"in y&&(g=y.hidden):y=J.access(e,"fxshow",{display:l}),o&&(y.hidden=!g),g&&fe([e],!0),p.done(function(){g||fe([e]),J.remove(e,"fxshow");for(r in d)w.style(e,r,d[r])})),u=lt(g?y[r]:0,r,p),r in y||(y[r]=u.start,g&&(u.end=u.start,u.start=0))}}function ft(e,t){var n,r,i,o,a;for(n in e)if(r=G(n),i=t[r],o=e[n],Array.isArray(o)&&(i=o[1],o=e[n]=o[0]),n!==r&&(e[r]=o,delete e[n]),(a=w.cssHooks[r])&&"expand"in a){o=a.expand(o),delete e[r];for(n in o)n in e||(e[n]=o[n],t[n]=i)}else t[r]=i}function pt(e,t,n){var r,i,o=0,a=pt.prefilters.length,s=w.Deferred().always(function(){delete u.elem}),u=function(){if(i)return!1;for(var t=nt||st(),n=Math.max(0,l.startTime+l.duration-t),r=1-(n/l.duration||0),o=0,a=l.tweens.length;o<a;o++)l.tweens[o].run(r);return s.notifyWith(e,[l,r,n]),r<1&&a?n:(a||s.notifyWith(e,[l,1,0]),s.resolveWith(e,[l]),!1)},l=s.promise({elem:e,props:w.extend({},t),opts:w.extend(!0,{specialEasing:{},easing:w.easing._default},n),originalProperties:t,originalOptions:n,startTime:nt||st(),duration:n.duration,tweens:[],createTween:function(t,n){var r=w.Tween(e,l.opts,t,n,l.opts.specialEasing[t]||l.opts.easing);return l.tweens.push(r),r},stop:function(t){var n=0,r=t?l.tweens.length:0;if(i)return this;for(i=!0;n<r;n++)l.tweens[n].run(1);return t?(s.notifyWith(e,[l,1,0]),s.resolveWith(e,[l,t])):s.rejectWith(e,[l,t]),this}}),c=l.props;for(ft(c,l.opts.specialEasing);o<a;o++)if(r=pt.prefilters[o].call(l,e,c,l.opts))return g(r.stop)&&(w._queueHooks(l.elem,l.opts.queue).stop=r.stop.bind(r)),r;return w.map(c,lt,l),g(l.opts.start)&&l.opts.start.call(e,l),l.progress(l.opts.progress).done(l.opts.done,l.opts.complete).fail(l.opts.fail).always(l.opts.always),w.fx.timer(w.extend(u,{elem:e,anim:l,queue:l.opts.queue})),l}w.Animation=w.extend(pt,{tweeners:{"*":[function(e,t){var n=this.createTween(e,t);return ue(n.elem,e,ie.exec(t),n),n}]},tweener:function(e,t){g(e)?(t=e,e=["*"]):e=e.match(M);for(var n,r=0,i=e.length;r<i;r++)n=e[r],pt.tweeners[n]=pt.tweeners[n]||[],pt.tweeners[n].unshift(t)},prefilters:[ct],prefilter:function(e,t){t?pt.prefilters.unshift(e):pt.prefilters.push(e)}}),w.speed=function(e,t,n){var r=e&&"object"==typeof e?w.extend({},e):{complete:n||!n&&t||g(e)&&e,duration:e,easing:n&&t||t&&!g(t)&&t};return w.fx.off?r.duration=0:"number"!=typeof r.duration&&(r.duration in w.fx.speeds?r.duration=w.fx.speeds[r.duration]:r.duration=w.fx.speeds._default),null!=r.queue&&!0!==r.queue||(r.queue="fx"),r.old=r.complete,r.complete=function(){g(r.old)&&r.old.call(this),r.queue&&w.dequeue(this,r.queue)},r},w.fn.extend({fadeTo:function(e,t,n,r){return this.filter(ae).css("opacity",0).show().end().animate({opacity:t},e,n,r)},animate:function(e,t,n,r){var i=w.isEmptyObject(e),o=w.speed(t,n,r),a=function(){var t=pt(this,w.extend({},e),o);(i||J.get(this,"finish"))&&t.stop(!0)};return a.finish=a,i||!1===o.queue?this.each(a):this.queue(o.queue,a)},stop:function(e,t,n){var r=function(e){var t=e.stop;delete e.stop,t(n)};return"string"!=typeof e&&(n=t,t=e,e=void 0),t&&!1!==e&&this.queue(e||"fx",[]),this.each(function(){var t=!0,i=null!=e&&e+"queueHooks",o=w.timers,a=J.get(this);if(i)a[i]&&a[i].stop&&r(a[i]);else for(i in a)a[i]&&a[i].stop&&ot.test(i)&&r(a[i]);for(i=o.length;i--;)o[i].elem!==this||null!=e&&o[i].queue!==e||(o[i].anim.stop(n),t=!1,o.splice(i,1));!t&&n||w.dequeue(this,e)})},finish:function(e){return!1!==e&&(e=e||"fx"),this.each(function(){var t,n=J.get(this),r=n[e+"queue"],i=n[e+"queueHooks"],o=w.timers,a=r?r.length:0;for(n.finish=!0,w.queue(this,e,[]),i&&i.stop&&i.stop.call(this,!0),t=o.length;t--;)o[t].elem===this&&o[t].queue===e&&(o[t].anim.stop(!0),o.splice(t,1));for(t=0;t<a;t++)r[t]&&r[t].finish&&r[t].finish.call(this);delete n.finish})}}),w.each(["toggle","show","hide"],function(e,t){var n=w.fn[t];w.fn[t]=function(e,r,i){return null==e||"boolean"==typeof e?n.apply(this,arguments):this.animate(ut(t,!0),e,r,i)}}),w.each({slideDown:ut("show"),slideUp:ut("hide"),slideToggle:ut("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(e,t){w.fn[e]=function(e,n,r){return this.animate(t,e,n,r)}}),w.timers=[],w.fx.tick=function(){var e,t=0,n=w.timers;for(nt=Date.now();t<n.length;t++)(e=n[t])()||n[t]!==e||n.splice(t--,1);n.length||w.fx.stop(),nt=void 0},w.fx.timer=function(e){w.timers.push(e),w.fx.start()},w.fx.interval=13,w.fx.start=function(){rt||(rt=!0,at())},w.fx.stop=function(){rt=null},w.fx.speeds={slow:600,fast:200,_default:400},w.fn.delay=function(t,n){return t=w.fx?w.fx.speeds[t]||t:t,n=n||"fx",this.queue(n,function(n,r){var i=e.setTimeout(n,t);r.stop=function(){e.clearTimeout(i)}})},function(){var e=r.createElement("input"),t=r.createElement("select").appendChild(r.createElement("option"));e.type="checkbox",h.checkOn=""!==e.value,h.optSelected=t.selected,(e=r.createElement("input")).value="t",e.type="radio",h.radioValue="t"===e.value}();var dt,ht=w.expr.attrHandle;w.fn.extend({attr:function(e,t){return z(this,w.attr,e,t,arguments.length>1)},removeAttr:function(e){return this.each(function(){w.removeAttr(this,e)})}}),w.extend({attr:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return"undefined"==typeof e.getAttribute?w.prop(e,t,n):(1===o&&w.isXMLDoc(e)||(i=w.attrHooks[t.toLowerCase()]||(w.expr.match.bool.test(t)?dt:void 0)),void 0!==n?null===n?void w.removeAttr(e,t):i&&"set"in i&&void 0!==(r=i.set(e,n,t))?r:(e.setAttribute(t,n+""),n):i&&"get"in i&&null!==(r=i.get(e,t))?r:null==(r=w.find.attr(e,t))?void 0:r)},attrHooks:{type:{set:function(e,t){if(!h.radioValue&&"radio"===t&&N(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},removeAttr:function(e,t){var n,r=0,i=t&&t.match(M);if(i&&1===e.nodeType)while(n=i[r++])e.removeAttribute(n)}}),dt={set:function(e,t,n){return!1===t?w.removeAttr(e,n):e.setAttribute(n,n),n}},w.each(w.expr.match.bool.source.match(/\w+/g),function(e,t){var n=ht[t]||w.find.attr;ht[t]=function(e,t,r){var i,o,a=t.toLowerCase();return r||(o=ht[a],ht[a]=i,i=null!=n(e,t,r)?a:null,ht[a]=o),i}});var gt=/^(?:input|select|textarea|button)$/i,yt=/^(?:a|area)$/i;w.fn.extend({prop:function(e,t){return z(this,w.prop,e,t,arguments.length>1)},removeProp:function(e){return this.each(function(){delete this[w.propFix[e]||e]})}}),w.extend({prop:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return 1===o&&w.isXMLDoc(e)||(t=w.propFix[t]||t,i=w.propHooks[t]),void 0!==n?i&&"set"in i&&void 0!==(r=i.set(e,n,t))?r:e[t]=n:i&&"get"in i&&null!==(r=i.get(e,t))?r:e[t]},propHooks:{tabIndex:{get:function(e){var t=w.find.attr(e,"tabindex");return t?parseInt(t,10):gt.test(e.nodeName)||yt.test(e.nodeName)&&e.href?0:-1}}},propFix:{"for":"htmlFor","class":"className"}}),h.optSelected||(w.propHooks.selected={get:function(e){var t=e.parentNode;return t&&t.parentNode&&t.parentNode.selectedIndex,null},set:function(e){var t=e.parentNode;t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex)}}),w.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){w.propFix[this.toLowerCase()]=this});function vt(e){return(e.match(M)||[]).join(" ")}function mt(e){return e.getAttribute&&e.getAttribute("class")||""}function xt(e){return Array.isArray(e)?e:"string"==typeof e?e.match(M)||[]:[]}w.fn.extend({addClass:function(e){var t,n,r,i,o,a,s,u=0;if(g(e))return this.each(function(t){w(this).addClass(e.call(this,t,mt(this)))});if((t=xt(e)).length)while(n=this[u++])if(i=mt(n),r=1===n.nodeType&&" "+vt(i)+" "){a=0;while(o=t[a++])r.indexOf(" "+o+" ")<0&&(r+=o+" ");i!==(s=vt(r))&&n.setAttribute("class",s)}return this},removeClass:function(e){var t,n,r,i,o,a,s,u=0;if(g(e))return this.each(function(t){w(this).removeClass(e.call(this,t,mt(this)))});if(!arguments.length)return this.attr("class","");if((t=xt(e)).length)while(n=this[u++])if(i=mt(n),r=1===n.nodeType&&" "+vt(i)+" "){a=0;while(o=t[a++])while(r.indexOf(" "+o+" ")>-1)r=r.replace(" "+o+" "," ");i!==(s=vt(r))&&n.setAttribute("class",s)}return this},toggleClass:function(e,t){var n=typeof e,r="string"===n||Array.isArray(e);return"boolean"==typeof t&&r?t?this.addClass(e):this.removeClass(e):g(e)?this.each(function(n){w(this).toggleClass(e.call(this,n,mt(this),t),t)}):this.each(function(){var t,i,o,a;if(r){i=0,o=w(this),a=xt(e);while(t=a[i++])o.hasClass(t)?o.removeClass(t):o.addClass(t)}else void 0!==e&&"boolean"!==n||((t=mt(this))&&J.set(this,"__className__",t),this.setAttribute&&this.setAttribute("class",t||!1===e?"":J.get(this,"__className__")||""))})},hasClass:function(e){var t,n,r=0;t=" "+e+" ";while(n=this[r++])if(1===n.nodeType&&(" "+vt(mt(n))+" ").indexOf(t)>-1)return!0;return!1}});var bt=/\r/g;w.fn.extend({val:function(e){var t,n,r,i=this[0];{if(arguments.length)return r=g(e),this.each(function(n){var i;1===this.nodeType&&(null==(i=r?e.call(this,n,w(this).val()):e)?i="":"number"==typeof i?i+="":Array.isArray(i)&&(i=w.map(i,function(e){return null==e?"":e+""})),(t=w.valHooks[this.type]||w.valHooks[this.nodeName.toLowerCase()])&&"set"in t&&void 0!==t.set(this,i,"value")||(this.value=i))});if(i)return(t=w.valHooks[i.type]||w.valHooks[i.nodeName.toLowerCase()])&&"get"in t&&void 0!==(n=t.get(i,"value"))?n:"string"==typeof(n=i.value)?n.replace(bt,""):null==n?"":n}}}),w.extend({valHooks:{option:{get:function(e){var t=w.find.attr(e,"value");return null!=t?t:vt(w.text(e))}},select:{get:function(e){var t,n,r,i=e.options,o=e.selectedIndex,a="select-one"===e.type,s=a?null:[],u=a?o+1:i.length;for(r=o<0?u:a?o:0;r<u;r++)if(((n=i[r]).selected||r===o)&&!n.disabled&&(!n.parentNode.disabled||!N(n.parentNode,"optgroup"))){if(t=w(n).val(),a)return t;s.push(t)}return s},set:function(e,t){var n,r,i=e.options,o=w.makeArray(t),a=i.length;while(a--)((r=i[a]).selected=w.inArray(w.valHooks.option.get(r),o)>-1)&&(n=!0);return n||(e.selectedIndex=-1),o}}}}),w.each(["radio","checkbox"],function(){w.valHooks[this]={set:function(e,t){if(Array.isArray(t))return e.checked=w.inArray(w(e).val(),t)>-1}},h.checkOn||(w.valHooks[this].get=function(e){return null===e.getAttribute("value")?"on":e.value})}),h.focusin="onfocusin"in e;var wt=/^(?:focusinfocus|focusoutblur)$/,Tt=function(e){e.stopPropagation()};w.extend(w.event,{trigger:function(t,n,i,o){var a,s,u,l,c,p,d,h,v=[i||r],m=f.call(t,"type")?t.type:t,x=f.call(t,"namespace")?t.namespace.split("."):[];if(s=h=u=i=i||r,3!==i.nodeType&&8!==i.nodeType&&!wt.test(m+w.event.triggered)&&(m.indexOf(".")>-1&&(m=(x=m.split(".")).shift(),x.sort()),c=m.indexOf(":")<0&&"on"+m,t=t[w.expando]?t:new w.Event(m,"object"==typeof t&&t),t.isTrigger=o?2:3,t.namespace=x.join("."),t.rnamespace=t.namespace?new RegExp("(^|\\.)"+x.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,t.result=void 0,t.target||(t.target=i),n=null==n?[t]:w.makeArray(n,[t]),d=w.event.special[m]||{},o||!d.trigger||!1!==d.trigger.apply(i,n))){if(!o&&!d.noBubble&&!y(i)){for(l=d.delegateType||m,wt.test(l+m)||(s=s.parentNode);s;s=s.parentNode)v.push(s),u=s;u===(i.ownerDocument||r)&&v.push(u.defaultView||u.parentWindow||e)}a=0;while((s=v[a++])&&!t.isPropagationStopped())h=s,t.type=a>1?l:d.bindType||m,(p=(J.get(s,"events")||{})[t.type]&&J.get(s,"handle"))&&p.apply(s,n),(p=c&&s[c])&&p.apply&&Y(s)&&(t.result=p.apply(s,n),!1===t.result&&t.preventDefault());return t.type=m,o||t.isDefaultPrevented()||d._default&&!1!==d._default.apply(v.pop(),n)||!Y(i)||c&&g(i[m])&&!y(i)&&((u=i[c])&&(i[c]=null),w.event.triggered=m,t.isPropagationStopped()&&h.addEventListener(m,Tt),i[m](),t.isPropagationStopped()&&h.removeEventListener(m,Tt),w.event.triggered=void 0,u&&(i[c]=u)),t.result}},simulate:function(e,t,n){var r=w.extend(new w.Event,n,{type:e,isSimulated:!0});w.event.trigger(r,null,t)}}),w.fn.extend({trigger:function(e,t){return this.each(function(){w.event.trigger(e,t,this)})},triggerHandler:function(e,t){var n=this[0];if(n)return w.event.trigger(e,t,n,!0)}}),h.focusin||w.each({focus:"focusin",blur:"focusout"},function(e,t){var n=function(e){w.event.simulate(t,e.target,w.event.fix(e))};w.event.special[t]={setup:function(){var r=this.ownerDocument||this,i=J.access(r,t);i||r.addEventListener(e,n,!0),J.access(r,t,(i||0)+1)},teardown:function(){var r=this.ownerDocument||this,i=J.access(r,t)-1;i?J.access(r,t,i):(r.removeEventListener(e,n,!0),J.remove(r,t))}}});var Ct=e.location,Et=Date.now(),kt=/\?/;w.parseXML=function(t){var n;if(!t||"string"!=typeof t)return null;try{n=(new e.DOMParser).parseFromString(t,"text/xml")}catch(e){n=void 0}return n&&!n.getElementsByTagName("parsererror").length||w.error("Invalid XML: "+t),n};var St=/\[\]$/,Dt=/\r?\n/g,Nt=/^(?:submit|button|image|reset|file)$/i,At=/^(?:input|select|textarea|keygen)/i;function jt(e,t,n,r){var i;if(Array.isArray(t))w.each(t,function(t,i){n||St.test(e)?r(e,i):jt(e+"["+("object"==typeof i&&null!=i?t:"")+"]",i,n,r)});else if(n||"object"!==x(t))r(e,t);else for(i in t)jt(e+"["+i+"]",t[i],n,r)}w.param=function(e,t){var n,r=[],i=function(e,t){var n=g(t)?t():t;r[r.length]=encodeURIComponent(e)+"="+encodeURIComponent(null==n?"":n)};if(Array.isArray(e)||e.jquery&&!w.isPlainObject(e))w.each(e,function(){i(this.name,this.value)});else for(n in e)jt(n,e[n],t,i);return r.join("&")},w.fn.extend({serialize:function(){return w.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var e=w.prop(this,"elements");return e?w.makeArray(e):this}).filter(function(){var e=this.type;return this.name&&!w(this).is(":disabled")&&At.test(this.nodeName)&&!Nt.test(e)&&(this.checked||!pe.test(e))}).map(function(e,t){var n=w(this).val();return null==n?null:Array.isArray(n)?w.map(n,function(e){return{name:t.name,value:e.replace(Dt,"\r\n")}}):{name:t.name,value:n.replace(Dt,"\r\n")}}).get()}});var qt=/%20/g,Lt=/#.*$/,Ht=/([?&])_=[^&]*/,Ot=/^(.*?):[ \t]*([^\r\n]*)$/gm,Pt=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Mt=/^(?:GET|HEAD)$/,Rt=/^\/\//,It={},Wt={},$t="*/".concat("*"),Bt=r.createElement("a");Bt.href=Ct.href;function Ft(e){return function(t,n){"string"!=typeof t&&(n=t,t="*");var r,i=0,o=t.toLowerCase().match(M)||[];if(g(n))while(r=o[i++])"+"===r[0]?(r=r.slice(1)||"*",(e[r]=e[r]||[]).unshift(n)):(e[r]=e[r]||[]).push(n)}}function _t(e,t,n,r){var i={},o=e===Wt;function a(s){var u;return i[s]=!0,w.each(e[s]||[],function(e,s){var l=s(t,n,r);return"string"!=typeof l||o||i[l]?o?!(u=l):void 0:(t.dataTypes.unshift(l),a(l),!1)}),u}return a(t.dataTypes[0])||!i["*"]&&a("*")}function zt(e,t){var n,r,i=w.ajaxSettings.flatOptions||{};for(n in t)void 0!==t[n]&&((i[n]?e:r||(r={}))[n]=t[n]);return r&&w.extend(!0,e,r),e}function Xt(e,t,n){var r,i,o,a,s=e.contents,u=e.dataTypes;while("*"===u[0])u.shift(),void 0===r&&(r=e.mimeType||t.getResponseHeader("Content-Type"));if(r)for(i in s)if(s[i]&&s[i].test(r)){u.unshift(i);break}if(u[0]in n)o=u[0];else{for(i in n){if(!u[0]||e.converters[i+" "+u[0]]){o=i;break}a||(a=i)}o=o||a}if(o)return o!==u[0]&&u.unshift(o),n[o]}function Ut(e,t,n,r){var i,o,a,s,u,l={},c=e.dataTypes.slice();if(c[1])for(a in e.converters)l[a.toLowerCase()]=e.converters[a];o=c.shift();while(o)if(e.responseFields[o]&&(n[e.responseFields[o]]=t),!u&&r&&e.dataFilter&&(t=e.dataFilter(t,e.dataType)),u=o,o=c.shift())if("*"===o)o=u;else if("*"!==u&&u!==o){if(!(a=l[u+" "+o]||l["* "+o]))for(i in l)if((s=i.split(" "))[1]===o&&(a=l[u+" "+s[0]]||l["* "+s[0]])){!0===a?a=l[i]:!0!==l[i]&&(o=s[0],c.unshift(s[1]));break}if(!0!==a)if(a&&e["throws"])t=a(t);else try{t=a(t)}catch(e){return{state:"parsererror",error:a?e:"No conversion from "+u+" to "+o}}}return{state:"success",data:t}}w.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:Ct.href,type:"GET",isLocal:Pt.test(Ct.protocol),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":$t,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/\bxml\b/,html:/\bhtml/,json:/\bjson\b/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":JSON.parse,"text xml":w.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(e,t){return t?zt(zt(e,w.ajaxSettings),t):zt(w.ajaxSettings,e)},ajaxPrefilter:Ft(It),ajaxTransport:Ft(Wt),ajax:function(t,n){"object"==typeof t&&(n=t,t=void 0),n=n||{};var i,o,a,s,u,l,c,f,p,d,h=w.ajaxSetup({},n),g=h.context||h,y=h.context&&(g.nodeType||g.jquery)?w(g):w.event,v=w.Deferred(),m=w.Callbacks("once memory"),x=h.statusCode||{},b={},T={},C="canceled",E={readyState:0,getResponseHeader:function(e){var t;if(c){if(!s){s={};while(t=Ot.exec(a))s[t[1].toLowerCase()]=t[2]}t=s[e.toLowerCase()]}return null==t?null:t},getAllResponseHeaders:function(){return c?a:null},setRequestHeader:function(e,t){return null==c&&(e=T[e.toLowerCase()]=T[e.toLowerCase()]||e,b[e]=t),this},overrideMimeType:function(e){return null==c&&(h.mimeType=e),this},statusCode:function(e){var t;if(e)if(c)E.always(e[E.status]);else for(t in e)x[t]=[x[t],e[t]];return this},abort:function(e){var t=e||C;return i&&i.abort(t),k(0,t),this}};if(v.promise(E),h.url=((t||h.url||Ct.href)+"").replace(Rt,Ct.protocol+"//"),h.type=n.method||n.type||h.method||h.type,h.dataTypes=(h.dataType||"*").toLowerCase().match(M)||[""],null==h.crossDomain){l=r.createElement("a");try{l.href=h.url,l.href=l.href,h.crossDomain=Bt.protocol+"//"+Bt.host!=l.protocol+"//"+l.host}catch(e){h.crossDomain=!0}}if(h.data&&h.processData&&"string"!=typeof h.data&&(h.data=w.param(h.data,h.traditional)),_t(It,h,n,E),c)return E;(f=w.event&&h.global)&&0==w.active++&&w.event.trigger("ajaxStart"),h.type=h.type.toUpperCase(),h.hasContent=!Mt.test(h.type),o=h.url.replace(Lt,""),h.hasContent?h.data&&h.processData&&0===(h.contentType||"").indexOf("application/x-www-form-urlencoded")&&(h.data=h.data.replace(qt,"+")):(d=h.url.slice(o.length),h.data&&(h.processData||"string"==typeof h.data)&&(o+=(kt.test(o)?"&":"?")+h.data,delete h.data),!1===h.cache&&(o=o.replace(Ht,"$1"),d=(kt.test(o)?"&":"?")+"_="+Et+++d),h.url=o+d),h.ifModified&&(w.lastModified[o]&&E.setRequestHeader("If-Modified-Since",w.lastModified[o]),w.etag[o]&&E.setRequestHeader("If-None-Match",w.etag[o])),(h.data&&h.hasContent&&!1!==h.contentType||n.contentType)&&E.setRequestHeader("Content-Type",h.contentType),E.setRequestHeader("Accept",h.dataTypes[0]&&h.accepts[h.dataTypes[0]]?h.accepts[h.dataTypes[0]]+("*"!==h.dataTypes[0]?", "+$t+"; q=0.01":""):h.accepts["*"]);for(p in h.headers)E.setRequestHeader(p,h.headers[p]);if(h.beforeSend&&(!1===h.beforeSend.call(g,E,h)||c))return E.abort();if(C="abort",m.add(h.complete),E.done(h.success),E.fail(h.error),i=_t(Wt,h,n,E)){if(E.readyState=1,f&&y.trigger("ajaxSend",[E,h]),c)return E;h.async&&h.timeout>0&&(u=e.setTimeout(function(){E.abort("timeout")},h.timeout));try{c=!1,i.send(b,k)}catch(e){if(c)throw e;k(-1,e)}}else k(-1,"No Transport");function k(t,n,r,s){var l,p,d,b,T,C=n;c||(c=!0,u&&e.clearTimeout(u),i=void 0,a=s||"",E.readyState=t>0?4:0,l=t>=200&&t<300||304===t,r&&(b=Xt(h,E,r)),b=Ut(h,b,E,l),l?(h.ifModified&&((T=E.getResponseHeader("Last-Modified"))&&(w.lastModified[o]=T),(T=E.getResponseHeader("etag"))&&(w.etag[o]=T)),204===t||"HEAD"===h.type?C="nocontent":304===t?C="notmodified":(C=b.state,p=b.data,l=!(d=b.error))):(d=C,!t&&C||(C="error",t<0&&(t=0))),E.status=t,E.statusText=(n||C)+"",l?v.resolveWith(g,[p,C,E]):v.rejectWith(g,[E,C,d]),E.statusCode(x),x=void 0,f&&y.trigger(l?"ajaxSuccess":"ajaxError",[E,h,l?p:d]),m.fireWith(g,[E,C]),f&&(y.trigger("ajaxComplete",[E,h]),--w.active||w.event.trigger("ajaxStop")))}return E},getJSON:function(e,t,n){return w.get(e,t,n,"json")},getScript:function(e,t){return w.get(e,void 0,t,"script")}}),w.each(["get","post"],function(e,t){w[t]=function(e,n,r,i){return g(n)&&(i=i||r,r=n,n=void 0),w.ajax(w.extend({url:e,type:t,dataType:i,data:n,success:r},w.isPlainObject(e)&&e))}}),w._evalUrl=function(e){return w.ajax({url:e,type:"GET",dataType:"script",cache:!0,async:!1,global:!1,"throws":!0})},w.fn.extend({wrapAll:function(e){var t;return this[0]&&(g(e)&&(e=e.call(this[0])),t=w(e,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstElementChild)e=e.firstElementChild;return e}).append(this)),this},wrapInner:function(e){return g(e)?this.each(function(t){w(this).wrapInner(e.call(this,t))}):this.each(function(){var t=w(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=g(e);return this.each(function(n){w(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(e){return this.parent(e).not("body").each(function(){w(this).replaceWith(this.childNodes)}),this}}),w.expr.pseudos.hidden=function(e){return!w.expr.pseudos.visible(e)},w.expr.pseudos.visible=function(e){return!!(e.offsetWidth||e.offsetHeight||e.getClientRects().length)},w.ajaxSettings.xhr=function(){try{return new e.XMLHttpRequest}catch(e){}};var Vt={0:200,1223:204},Gt=w.ajaxSettings.xhr();h.cors=!!Gt&&"withCredentials"in Gt,h.ajax=Gt=!!Gt,w.ajaxTransport(function(t){var n,r;if(h.cors||Gt&&!t.crossDomain)return{send:function(i,o){var a,s=t.xhr();if(s.open(t.type,t.url,t.async,t.username,t.password),t.xhrFields)for(a in t.xhrFields)s[a]=t.xhrFields[a];t.mimeType&&s.overrideMimeType&&s.overrideMimeType(t.mimeType),t.crossDomain||i["X-Requested-With"]||(i["X-Requested-With"]="XMLHttpRequest");for(a in i)s.setRequestHeader(a,i[a]);n=function(e){return function(){n&&(n=r=s.onload=s.onerror=s.onabort=s.ontimeout=s.onreadystatechange=null,"abort"===e?s.abort():"error"===e?"number"!=typeof s.status?o(0,"error"):o(s.status,s.statusText):o(Vt[s.status]||s.status,s.statusText,"text"!==(s.responseType||"text")||"string"!=typeof s.responseText?{binary:s.response}:{text:s.responseText},s.getAllResponseHeaders()))}},s.onload=n(),r=s.onerror=s.ontimeout=n("error"),void 0!==s.onabort?s.onabort=r:s.onreadystatechange=function(){4===s.readyState&&e.setTimeout(function(){n&&r()})},n=n("abort");try{s.send(t.hasContent&&t.data||null)}catch(e){if(n)throw e}},abort:function(){n&&n()}}}),w.ajaxPrefilter(function(e){e.crossDomain&&(e.contents.script=!1)}),w.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/\b(?:java|ecma)script\b/},converters:{"text script":function(e){return w.globalEval(e),e}}}),w.ajaxPrefilter("script",function(e){void 0===e.cache&&(e.cache=!1),e.crossDomain&&(e.type="GET")}),w.ajaxTransport("script",function(e){if(e.crossDomain){var t,n;return{send:function(i,o){t=w("<script>").prop({charset:e.scriptCharset,src:e.url}).on("load error",n=function(e){t.remove(),n=null,e&&o("error"===e.type?404:200,e.type)}),r.head.appendChild(t[0])},abort:function(){n&&n()}}}});var Yt=[],Qt=/(=)\?(?=&|$)|\?\?/;w.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Yt.pop()||w.expando+"_"+Et++;return this[e]=!0,e}}),w.ajaxPrefilter("json jsonp",function(t,n,r){var i,o,a,s=!1!==t.jsonp&&(Qt.test(t.url)?"url":"string"==typeof t.data&&0===(t.contentType||"").indexOf("application/x-www-form-urlencoded")&&Qt.test(t.data)&&"data");if(s||"jsonp"===t.dataTypes[0])return i=t.jsonpCallback=g(t.jsonpCallback)?t.jsonpCallback():t.jsonpCallback,s?t[s]=t[s].replace(Qt,"$1"+i):!1!==t.jsonp&&(t.url+=(kt.test(t.url)?"&":"?")+t.jsonp+"="+i),t.converters["script json"]=function(){return a||w.error(i+" was not called"),a[0]},t.dataTypes[0]="json",o=e[i],e[i]=function(){a=arguments},r.always(function(){void 0===o?w(e).removeProp(i):e[i]=o,t[i]&&(t.jsonpCallback=n.jsonpCallback,Yt.push(i)),a&&g(o)&&o(a[0]),a=o=void 0}),"script"}),h.createHTMLDocument=function(){var e=r.implementation.createHTMLDocument("").body;return e.innerHTML="<form></form><form></form>",2===e.childNodes.length}(),w.parseHTML=function(e,t,n){if("string"!=typeof e)return[];"boolean"==typeof t&&(n=t,t=!1);var i,o,a;return t||(h.createHTMLDocument?((i=(t=r.implementation.createHTMLDocument("")).createElement("base")).href=r.location.href,t.head.appendChild(i)):t=r),o=A.exec(e),a=!n&&[],o?[t.createElement(o[1])]:(o=xe([e],t,a),a&&a.length&&w(a).remove(),w.merge([],o.childNodes))},w.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return s>-1&&(r=vt(e.slice(s)),e=e.slice(0,s)),g(t)?(n=t,t=void 0):t&&"object"==typeof t&&(i="POST"),a.length>0&&w.ajax({url:e,type:i||"GET",dataType:"html",data:t}).done(function(e){o=arguments,a.html(r?w("<div>").append(w.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},w.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){w.fn[t]=function(e){return this.on(t,e)}}),w.expr.pseudos.animated=function(e){return w.grep(w.timers,function(t){return e===t.elem}).length},w.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l,c=w.css(e,"position"),f=w(e),p={};"static"===c&&(e.style.position="relative"),s=f.offset(),o=w.css(e,"top"),u=w.css(e,"left"),(l=("absolute"===c||"fixed"===c)&&(o+u).indexOf("auto")>-1)?(a=(r=f.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),g(t)&&(t=t.call(e,n,w.extend({},s))),null!=t.top&&(p.top=t.top-s.top+a),null!=t.left&&(p.left=t.left-s.left+i),"using"in t?t.using.call(e,p):f.css(p)}},w.fn.extend({offset:function(e){if(arguments.length)return void 0===e?this:this.each(function(t){w.offset.setOffset(this,e,t)});var t,n,r=this[0];if(r)return r.getClientRects().length?(t=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:t.top+n.pageYOffset,left:t.left+n.pageXOffset}):{top:0,left:0}},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===w.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===w.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=w(e).offset()).top+=w.css(e,"borderTopWidth",!0),i.left+=w.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-w.css(r,"marginTop",!0),left:t.left-i.left-w.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===w.css(e,"position"))e=e.offsetParent;return e||be})}}),w.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(e,t){var n="pageYOffset"===t;w.fn[e]=function(r){return z(this,function(e,r,i){var o;if(y(e)?o=e:9===e.nodeType&&(o=e.defaultView),void 0===i)return o?o[t]:e[r];o?o.scrollTo(n?o.pageXOffset:i,n?i:o.pageYOffset):e[r]=i},e,r,arguments.length)}}),w.each(["top","left"],function(e,t){w.cssHooks[t]=_e(h.pixelPosition,function(e,n){if(n)return n=Fe(e,t),We.test(n)?w(e).position()[t]+"px":n})}),w.each({Height:"height",Width:"width"},function(e,t){w.each({padding:"inner"+e,content:t,"":"outer"+e},function(n,r){w.fn[r]=function(i,o){var a=arguments.length&&(n||"boolean"!=typeof i),s=n||(!0===i||!0===o?"margin":"border");return z(this,function(t,n,i){var o;return y(t)?0===r.indexOf("outer")?t["inner"+e]:t.document.documentElement["client"+e]:9===t.nodeType?(o=t.documentElement,Math.max(t.body["scroll"+e],o["scroll"+e],t.body["offset"+e],o["offset"+e],o["client"+e])):void 0===i?w.css(t,n,s):w.style(t,n,i,s)},t,a?i:void 0,a)}})}),w.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,t){w.fn[t]=function(e,n){return arguments.length>0?this.on(t,null,e,n):this.trigger(t)}}),w.fn.extend({hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),w.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)}}),w.proxy=function(e,t){var n,r,i;if("string"==typeof t&&(n=e[t],t=e,e=n),g(e))return r=o.call(arguments,2),i=function(){return e.apply(t||this,r.concat(o.call(arguments)))},i.guid=e.guid=e.guid||w.guid++,i},w.holdReady=function(e){e?w.readyWait++:w.ready(!0)},w.isArray=Array.isArray,w.parseJSON=JSON.parse,w.nodeName=N,w.isFunction=g,w.isWindow=y,w.camelCase=G,w.type=x,w.now=Date.now,w.isNumeric=function(e){var t=w.type(e);return("number"===t||"string"===t)&&!isNaN(e-parseFloat(e))},"function"==typeof define&&define.amd&&define("jquery",[],function(){return w});var Jt=e.jQuery,Kt=e.$;return w.noConflict=function(t){return e.$===w&&(e.$=Kt),t&&e.jQuery===w&&(e.jQuery=Jt),w},t||(e.jQuery=e.$=w),w});
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
"use strict";var Module={};var initializedJS=false;function threadPrintErr(){var text=Array.prototype.slice.call(arguments).join(" ");console.error(text)}function threadAlert(){var text=Array.prototype.slice.call(arguments).join(" ");postMessage({cmd:"alert",text:text,threadId:Module["_pthread_self"]()})}var err=threadPrintErr;self.alert=threadAlert;Module["instantiateWasm"]=(info,receiveInstance)=>{var module=Module["wasmModule"];Module["wasmModule"]=null;var instance=new WebAssembly.Instance(module,info);return receiveInstance(instance)};self.onunhandledrejection=e=>{throw e.reason??e};function handleMessage(e){try{if(e.data.cmd==="load"){let messageQueue=[];self.onmessage=e=>messageQueue.push(e);self.startWorker=instance=>{Module=instance;postMessage({"cmd":"loaded"});for(let msg of messageQueue){handleMessage(msg)}self.onmessage=handleMessage};Module["wasmModule"]=e.data.wasmModule;for(const handler of e.data.handlers){Module[handler]=(...args)=>{postMessage({cmd:"callHandler",handler:handler,args:args})}}Module["wasmMemory"]=e.data.wasmMemory;Module["buffer"]=Module["wasmMemory"].buffer;Module["ENVIRONMENT_IS_PTHREAD"]=true;if(typeof e.data.urlOrBlob=="string"){importScripts(e.data.urlOrBlob)}else{var objectUrl=URL.createObjectURL(e.data.urlOrBlob);importScripts(objectUrl);URL.revokeObjectURL(objectUrl)}JSPlayerModule(Module)}else if(e.data.cmd==="run"){Module["__emscripten_thread_init"](e.data.pthread_ptr,0,0,1);Module["__emscripten_thread_mailbox_await"](e.data.pthread_ptr);Module["establishStackSpace"]();Module["PThread"].receiveObjectTransfer(e.data);Module["PThread"].threadInitTLS();if(!initializedJS){Module["__embind_initialize_bindings"]();initializedJS=true}try{Module["invokeEntryPoint"](e.data.start_routine,e.data.arg)}catch(ex){if(ex!="unwind"){throw ex}}}else if(e.data.cmd==="cancel"){if(Module["_pthread_self"]()){Module["__emscripten_thread_exit"](-1)}}else if(e.data.target==="setimmediate"){}else if(e.data.cmd==="checkMailbox"){if(initializedJS){Module["checkMailbox"]()}}else if(e.data.cmd){err("worker.js received unknown command "+e.data.cmd);err(e.data)}}catch(ex){if(Module["__emscripten_thread_crashed"]){Module["__emscripten_thread_crashed"]()}throw ex}}self.onmessage=handleMessage;
This source diff could not be displayed because it is too large. You can view the blob instead.
"use strict";var Module={};var initializedJS=false;function threadPrintErr(){var text=Array.prototype.slice.call(arguments).join(" ");console.error(text)}function threadAlert(){var text=Array.prototype.slice.call(arguments).join(" ");postMessage({cmd:"alert",text:text,threadId:Module["_pthread_self"]()})}var err=threadPrintErr;self.alert=threadAlert;Module["instantiateWasm"]=(info,receiveInstance)=>{var module=Module["wasmModule"];Module["wasmModule"]=null;var instance=new WebAssembly.Instance(module,info);return receiveInstance(instance)};self.onunhandledrejection=e=>{throw e.reason??e};function handleMessage(e){try{if(e.data.cmd==="load"){let messageQueue=[];self.onmessage=e=>messageQueue.push(e);self.startWorker=instance=>{Module=instance;postMessage({"cmd":"loaded"});for(let msg of messageQueue){handleMessage(msg)}self.onmessage=handleMessage};Module["wasmModule"]=e.data.wasmModule;for(const handler of e.data.handlers){Module[handler]=(...args)=>{postMessage({cmd:"callHandler",handler:handler,args:args})}}Module["wasmMemory"]=e.data.wasmMemory;Module["buffer"]=Module["wasmMemory"].buffer;Module["ENVIRONMENT_IS_PTHREAD"]=true;if(typeof e.data.urlOrBlob=="string"){importScripts(e.data.urlOrBlob)}else{var objectUrl=URL.createObjectURL(e.data.urlOrBlob);importScripts(objectUrl);URL.revokeObjectURL(objectUrl)}JSPlayerModule(Module)}else if(e.data.cmd==="run"){Module["__emscripten_thread_init"](e.data.pthread_ptr,0,0,1);Module["__emscripten_thread_mailbox_await"](e.data.pthread_ptr);Module["establishStackSpace"]();Module["PThread"].receiveObjectTransfer(e.data);Module["PThread"].threadInitTLS();if(!initializedJS){Module["__embind_initialize_bindings"]();initializedJS=true}try{Module["invokeEntryPoint"](e.data.start_routine,e.data.arg)}catch(ex){if(ex!="unwind"){throw ex}}}else if(e.data.cmd==="cancel"){if(Module["_pthread_self"]()){Module["__emscripten_thread_exit"](-1)}}else if(e.data.target==="setimmediate"){}else if(e.data.cmd==="checkMailbox"){if(initializedJS){Module["checkMailbox"]()}}else if(e.data.cmd){err("worker.js received unknown command "+e.data.cmd);err(e.data)}}catch(ex){if(Module["__emscripten_thread_crashed"]){Module["__emscripten_thread_crashed"]()}throw ex}}self.onmessage=handleMessage;
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
importScripts('libSystemTransform.js');
const RECORDRTP = 0; //录制一份未经过转封装的码流原始数据,用于定位问题
let dataType = 1;
// 字母字符串转byte数组
function stringToBytes (str) {
var ch;
var st;
var re = [];
for (var i = 0; i < str.length; i++) {
ch = str.charCodeAt(i); // get char
st = []; // set up "stack"
do {
st.push(ch & 0xFF); // push byte to stack
ch = ch >> 8; // shift value down by 1 byte
}
while (ch);
// add stack contents to result
// done because chars have "wrong" endianness
re = re.concat(st.reverse());
}
// return an array of bytes
return re;
}
// 转封装库回调函数
self.STCallBack = function (fileIndex, indexLen, data, dataLen) {
//stFrameInfo的类型见DETAIL_FRAME_INFO
let stFrameInfo = Module._GetDetialFrameInfo();
let nIsMp4Index = stFrameInfo.nIsMp4Index;
//console.log("FrameType is " , stFrameInfo);
//console.log("nIsMp4Index is " + nIsMp4Index);
//debugger
var pData = null;
pData = new Uint8Array(dataLen);
pData.set(Module.HEAPU8.subarray(data, data + dataLen));
if (dataType === 1) {
postMessage({ type: "outputData",
buf: pData.buffer,
dType: 1,
frameInfo: stFrameInfo }, [pData.buffer]);
dataType = 2;
} else {
if (nIsMp4Index) {
postMessage({ type: "outputData",
buf: pData.buffer,
dType: 6,
frameInfo: stFrameInfo }, [pData.buffer]); //6:索引类型
} else {
postMessage({ type: "outputData",
buf: pData.buffer,
dType: 2,
frameInfo: stFrameInfo }, [pData.buffer]); //2:码流
}
}
//stFrameInfo的类型见DETAIL_FRAME_INFO
//let stFrameInfo = Module._GetDetialFrameInfo();
//let stFrameType = stFrameInfo.nFrameType;
//let nFrameNum = stFrameInfo.nFrameNum;
//let nTimeStamp = stFrameInfo.nTimeStamp;
//let nIsMp4Index = stFrameInfo.nIsMp4Index;
//console.log("FrameType is " + stFrameType);
//console.log("nIsMp4Index is " + nIsMp4Index);
};
// self.Module = { memoryInitializerRequest: loadMemInitFile(), TOTAL_MEMORY: 128*1024*1024 };
// importScripts('SystemTransform.js');
self.Module['onRuntimeInitialized'] = function () {
postMessage({type: "loaded"});
};
onmessage = function (e) {
var data = e.data;
if ("create" === data.type) {
if (RECORDRTP) {
postMessage({ type: "created" });
postMessage({ type: "outputData",
buf: data.buf,
dType: 1 }, [data.buf]);
} else {
var iHeadLen = data.len;
var pHead = Module._malloc(iHeadLen);
if (pHead === null) {
console.log("inputdata malloc failed!!!");
return -1;
}
var iTransType = data.packType;//目标格式
var iRet = 0;
var buf = new Uint8Array(data.buf);
//PS流(只有ps支持探测),并且编码格式异常(正常是265和264,11位和10位 不可能全是0,全0 并且是ps就探测策略)的情况下,使用探测策略
if (buf[9] === 0 && buf[8] === 2 && buf[11] === 0 && buf[10] === 0) {
iRet = Module._CreatHandle(0, iTransType, iHeadLen); //用探测的策略
} else {
self.writeArrayToMemory(buf, pHead);
iRet = Module._CreatHandle(pHead, iTransType, iHeadLen);
//-2147483645代表的是参数错误,此种情况,大概率发生在头信息错误,例如大华设备的情况,此时用 无头探测的策略
//其他情况 按海康标准处理流程,不要做任何特殊处理
if (iRet == -2147483645) {
iRet = Module._CreatHandle(0, iTransType, iHeadLen); //失败了,用探测的策略再试一次
}
}
if (iRet != 0) {
if (iRet == -2147483647) {
postMessage({ type: "outputData",
dType: 1501 }); //标记为格式不支持
} else {
postMessage({ type: "outputData",
dType: 1501 }); //转封装创建失败,也同样提示码流格式不支持,如果后续要细化再区分
}
console.log("_CreatHandle failed!" + iRet);
} else {
if (data.options && typeof data.options.pKeyData !== "undefined" && data.options.pKeyData !== null) {
if ((2 === iTransType && "" === data.options.pKeyData)) {
//转ps的时候,如果密码是空是允许的,即使码流加密了,导出加密后的码流就行
//此时不要设置密码否则反而会提示密码错误
} else {
var secretInfo = data.options;
var keyLen = secretInfo.nKeyLen;
var pKeyData = Module._malloc(keyLen);
if (pKeyData === null) {
console.log("setEncryptKey malloc failed!!!");
return -1;
}
var nKeySize = secretInfo.pKeyData.length;
var bufData = stringToBytes(secretInfo.pKeyData);
let inputData = new Uint8Array(bufData);
Module.writeArrayToMemory(inputData, pKeyData);
inputData = null;
iRet = Module._SysTransSetEncryptKey(secretInfo.nKeyType, pKeyData, keyLen, nKeySize);
if (iRet != 0) {
console.log("_SysTransSetEncryptKey failed!");
}
if (pKeyData != null) {
Module._free(pKeyData);
pKeyData = null;
}
}
}
//带samplingParam参数,代表需要 用到 音频替换功能
if (data.options && typeof data.options.samplingParam !== "undefined") {
var oParam = data.options.samplingParam;
var nCapacityType = 1; //写死1 代表 剔除音频
var nType = 3; //写死3 代表 修改输出目标的海康头配置,内部包含视频参数、音频参数
var nAudioEnable = 1; //音频参数修改使能开关,0=不启用,1=启用
var nAudioFormat = oParam.iAudioType; //音频编码类型 对应关系参考海康媒体头规范,PCM 0x7001 G711_U 0x7110 G711_A 0x7111 AAC 0x2001
var nAudioChannels = oParam.iChannel; //音频通道数直接设置为
var nAudioBitsPerSample = oParam.iAudioBitWidth; //音频位样率
var nAudioSamplesrate = oParam.iAudioSamplingRate; //音频采样率
var nAudioBitrate = oParam.iAudioBitRate; //音频比特率
iRet = Module._SysTransConfig(nCapacityType, nType, nAudioEnable, nAudioFormat,
nAudioChannels, nAudioBitsPerSample, nAudioSamplesrate, nAudioBitrate);
if (iRet != 0) {
console.log("_SysTransConfig Failed:" + iRet);
}
} else {
iRet = Module._SysTransConfig(128, 0, 0, 0, 0, 0, 0, 0); //nCapacityType = 0x00000080 代表开启私有信息回调 解决转mp4后,私有信息丢失问题
if (iRet != 0) {
console.log("_SysTransConfig Failed:" + iRet);
}
}
iRet = Module._SysTransRegisterDataCallBack();
if (iRet != 0) {
console.log("_SysTransRegisterDataCallBack Failed:" + iRet);
}
iRet = Module._SysTransStart(null, null);
if (iRet != 0) {
console.log("_SysTransStart Failed:" + iRet);
}
postMessage({type: "created"});
}
if (pHead != null) {
Module._free(pHead);
pHead = null;
}
}
} else if ("inputData" === data.type) {
if (RECORDRTP) {
var aFileData = new Uint8Array(data.buf); // 拷贝一份
var iBufferLen = aFileData.length;
var szBufferLen = iBufferLen.toString(16);
if (szBufferLen.length === 1) {
szBufferLen = "000" + szBufferLen;
} else if (szBufferLen.length === 2) {
szBufferLen = "00" + szBufferLen;
} else if (szBufferLen.length === 3) {
szBufferLen = "0" + szBufferLen;
}
var aData = [0, 0, parseInt(szBufferLen.substring(0, 2), 16), parseInt(szBufferLen.substring(2, 4), 16)];
for (var iIndex = 0, iDataLength = aFileData.length; iIndex < iDataLength; iIndex++) {
aData[iIndex + 4] = aFileData[iIndex];
}
var dataUint8 = new Uint8Array(aData);
postMessage({type: "outputData",
buf: dataUint8.buffer,
dType: 2});
} else {
let inputMode = 0; //代表输入原始数据
if (data.samplingParam) {
iRet = Module._SysTransInputAudioPara(5, data.samplingParam.iChannel, data.samplingParam.iAudioBitWidth,
data.samplingParam.iAudioSamplingRate, data.samplingParam.iTimeStamp, data.samplingParam.iAudioBitRate); //参数含义和_SysTransConfig类似
if (iRet != 0) {
console.log("_SysTransInputAudioPara Failed:" + iRet);
}
inputMode = 2; //输入替换的音频
}
var pInputDataBuf = Module._malloc(data.len);
var idataLen = data.len;
self.writeArrayToMemory(new Uint8Array(data.buf), pInputDataBuf);
// 输入数据,每次最多2m
let pp = Module._SysTransInputData(inputMode, pInputDataBuf, idataLen);
if (pp == -2147483627) {
//-2147483627 对应十六进制的80000015
postMessage({ type: "outputData",
dType: 1500 }); //标记为密码错误
} else if (pp == -2147483647) {
postMessage({ type: "outputData",
dType: 1501 }); //标记为格式不支持
} else if (pp != 0) {
console.log("InputData Failed:" + pp);
}
Module._free(pInputDataBuf);
}
} else if ("release" === data.type) {
var iRet = Module._SysTransStop();
if (iRet != 0) {
console.log("_SysTransStop failed!");
}
Module._SysTransRelease();
if (iRet != 0) {
console.log("_SysTransRelease failed!");
}
close();
}
};
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
/** vim: et:ts=4:sw=4:sts=4
* @license RequireJS 2.3.3 Copyright jQuery Foundation and other contributors.
* Released under MIT license, https://github.com/requirejs/requirejs/blob/master/LICENSE
*/
var requirejs,require,define;!function(global,setTimeout){function commentReplace(e,t){return t||""}function isFunction(e){return"[object Function]"===ostring.call(e)}function isArray(e){return"[object Array]"===ostring.call(e)}function each(e,t){if(e){var i;for(i=0;i<e.length&&(!e[i]||!t(e[i],i,e));i+=1);}}function eachReverse(e,t){if(e){var i;for(i=e.length-1;i>-1&&(!e[i]||!t(e[i],i,e));i-=1);}}function hasProp(e,t){return hasOwn.call(e,t)}function getOwn(e,t){return hasProp(e,t)&&e[t]}function eachProp(e,t){var i;for(i in e)if(hasProp(e,i)&&t(e[i],i))break}function mixin(e,t,i,r){return t&&eachProp(t,function(t,n){!i&&hasProp(e,n)||(!r||"object"!=typeof t||!t||isArray(t)||isFunction(t)||t instanceof RegExp?e[n]=t:(e[n]||(e[n]={}),mixin(e[n],t,i,r)))}),e}function bind(e,t){return function(){return t.apply(e,arguments)}}function scripts(){return document.getElementsByTagName("script")}function defaultOnError(e){throw e}function getGlobal(e){if(!e)return e;var t=global;return each(e.split("."),function(e){t=t[e]}),t}function makeError(e,t,i,r){var n=new Error(t+"\nhttp://requirejs.org/docs/errors.html#"+e);return n.requireType=e,n.requireModules=r,i&&(n.originalError=i),n}function newContext(e){function t(e){var t,i;for(t=0;t<e.length;t++)if(i=e[t],"."===i)e.splice(t,1),t-=1;else if(".."===i){if(0===t||1===t&&".."===e[2]||".."===e[t-1])continue;t>0&&(e.splice(t-1,2),t-=2)}}function i(e,i,r){var n,o,a,s,u,c,d,p,f,l,h,m,g=i&&i.split("/"),v=y.map,x=v&&v["*"];if(e&&(e=e.split("/"),d=e.length-1,y.nodeIdCompat&&jsSuffixRegExp.test(e[d])&&(e[d]=e[d].replace(jsSuffixRegExp,"")),"."===e[0].charAt(0)&&g&&(m=g.slice(0,g.length-1),e=m.concat(e)),t(e),e=e.join("/")),r&&v&&(g||x)){a=e.split("/");e:for(s=a.length;s>0;s-=1){if(c=a.slice(0,s).join("/"),g)for(u=g.length;u>0;u-=1)if(o=getOwn(v,g.slice(0,u).join("/")),o&&(o=getOwn(o,c))){p=o,f=s;break e}!l&&x&&getOwn(x,c)&&(l=getOwn(x,c),h=s)}!p&&l&&(p=l,f=h),p&&(a.splice(0,f,p),e=a.join("/"))}return n=getOwn(y.pkgs,e),n?n:e}function r(e){isBrowser&&each(scripts(),function(t){if(t.getAttribute("data-requiremodule")===e&&t.getAttribute("data-requirecontext")===q.contextName)return t.parentNode.removeChild(t),!0})}function n(e){var t=getOwn(y.paths,e);if(t&&isArray(t)&&t.length>1)return t.shift(),q.require.undef(e),q.makeRequire(null,{skipMap:!0})([e]),!0}function o(e){var t,i=e?e.indexOf("!"):-1;return i>-1&&(t=e.substring(0,i),e=e.substring(i+1,e.length)),[t,e]}function a(e,t,r,n){var a,s,u,c,d=null,p=t?t.name:null,f=e,l=!0,h="";return e||(l=!1,e="_@r"+(T+=1)),c=o(e),d=c[0],e=c[1],d&&(d=i(d,p,n),s=getOwn(j,d)),e&&(d?h=r?e:s&&s.normalize?s.normalize(e,function(e){return i(e,p,n)}):e.indexOf("!")===-1?i(e,p,n):e:(h=i(e,p,n),c=o(h),d=c[0],h=c[1],r=!0,a=q.nameToUrl(h))),u=!d||s||r?"":"_unnormalized"+(A+=1),{prefix:d,name:h,parentMap:t,unnormalized:!!u,url:a,originalName:f,isDefine:l,id:(d?d+"!"+h:h)+u}}function s(e){var t=e.id,i=getOwn(S,t);return i||(i=S[t]=new q.Module(e)),i}function u(e,t,i){var r=e.id,n=getOwn(S,r);!hasProp(j,r)||n&&!n.defineEmitComplete?(n=s(e),n.error&&"error"===t?i(n.error):n.on(t,i)):"defined"===t&&i(j[r])}function c(e,t){var i=e.requireModules,r=!1;t?t(e):(each(i,function(t){var i=getOwn(S,t);i&&(i.error=e,i.events.error&&(r=!0,i.emit("error",e)))}),r||req.onError(e))}function d(){globalDefQueue.length&&(each(globalDefQueue,function(e){var t=e[0];"string"==typeof t&&(q.defQueueMap[t]=!0),O.push(e)}),globalDefQueue=[])}function p(e){delete S[e],delete k[e]}function f(e,t,i){var r=e.map.id;e.error?e.emit("error",e.error):(t[r]=!0,each(e.depMaps,function(r,n){var o=r.id,a=getOwn(S,o);!a||e.depMatched[n]||i[o]||(getOwn(t,o)?(e.defineDep(n,j[o]),e.check()):f(a,t,i))}),i[r]=!0)}function l(){var e,t,i=1e3*y.waitSeconds,o=i&&q.startTime+i<(new Date).getTime(),a=[],s=[],u=!1,d=!0;if(!x){if(x=!0,eachProp(k,function(e){var i=e.map,c=i.id;if(e.enabled&&(i.isDefine||s.push(e),!e.error))if(!e.inited&&o)n(c)?(t=!0,u=!0):(a.push(c),r(c));else if(!e.inited&&e.fetched&&i.isDefine&&(u=!0,!i.prefix))return d=!1}),o&&a.length)return e=makeError("timeout","Load timeout for modules: "+a,null,a),e.contextName=q.contextName,c(e);d&&each(s,function(e){f(e,{},{})}),o&&!t||!u||!isBrowser&&!isWebWorker||w||(w=setTimeout(function(){w=0,l()},50)),x=!1}}function h(e){hasProp(j,e[0])||s(a(e[0],null,!0)).init(e[1],e[2])}function m(e,t,i,r){e.detachEvent&&!isOpera?r&&e.detachEvent(r,t):e.removeEventListener(i,t,!1)}function g(e){var t=e.currentTarget||e.srcElement;return m(t,q.onScriptLoad,"load","onreadystatechange"),m(t,q.onScriptError,"error"),{node:t,id:t&&t.getAttribute("data-requiremodule")}}function v(){var e;for(d();O.length;){if(e=O.shift(),null===e[0])return c(makeError("mismatch","Mismatched anonymous define() module: "+e[e.length-1]));h(e)}q.defQueueMap={}}var x,b,q,E,w,y={waitSeconds:7,baseUrl:"./",paths:{},bundles:{},pkgs:{},shim:{},config:{}},S={},k={},M={},O=[],j={},P={},R={},T=1,A=1;return E={require:function(e){return e.require?e.require:e.require=q.makeRequire(e.map)},exports:function(e){if(e.usingExports=!0,e.map.isDefine)return e.exports?j[e.map.id]=e.exports:e.exports=j[e.map.id]={}},module:function(e){return e.module?e.module:e.module={id:e.map.id,uri:e.map.url,config:function(){return getOwn(y.config,e.map.id)||{}},exports:e.exports||(e.exports={})}}},b=function(e){this.events=getOwn(M,e.id)||{},this.map=e,this.shim=getOwn(y.shim,e.id),this.depExports=[],this.depMaps=[],this.depMatched=[],this.pluginMaps={},this.depCount=0},b.prototype={init:function(e,t,i,r){r=r||{},this.inited||(this.factory=t,i?this.on("error",i):this.events.error&&(i=bind(this,function(e){this.emit("error",e)})),this.depMaps=e&&e.slice(0),this.errback=i,this.inited=!0,this.ignore=r.ignore,r.enabled||this.enabled?this.enable():this.check())},defineDep:function(e,t){this.depMatched[e]||(this.depMatched[e]=!0,this.depCount-=1,this.depExports[e]=t)},fetch:function(){if(!this.fetched){this.fetched=!0,q.startTime=(new Date).getTime();var e=this.map;return this.shim?void q.makeRequire(this.map,{enableBuildCallback:!0})(this.shim.deps||[],bind(this,function(){return e.prefix?this.callPlugin():this.load()})):e.prefix?this.callPlugin():this.load()}},load:function(){var e=this.map.url;P[e]||(P[e]=!0,q.load(this.map.id,e))},check:function(){if(this.enabled&&!this.enabling){var e,t,i=this.map.id,r=this.depExports,n=this.exports,o=this.factory;if(this.inited){if(this.error)this.emit("error",this.error);else if(!this.defining){if(this.defining=!0,this.depCount<1&&!this.defined){if(isFunction(o)){if(this.events.error&&this.map.isDefine||req.onError!==defaultOnError)try{n=q.execCb(i,o,r,n)}catch(t){e=t}else n=q.execCb(i,o,r,n);if(this.map.isDefine&&void 0===n&&(t=this.module,t?n=t.exports:this.usingExports&&(n=this.exports)),e)return e.requireMap=this.map,e.requireModules=this.map.isDefine?[this.map.id]:null,e.requireType=this.map.isDefine?"define":"require",c(this.error=e)}else n=o;if(this.exports=n,this.map.isDefine&&!this.ignore&&(j[i]=n,req.onResourceLoad)){var a=[];each(this.depMaps,function(e){a.push(e.normalizedMap||e)}),req.onResourceLoad(q,this.map,a)}p(i),this.defined=!0}this.defining=!1,this.defined&&!this.defineEmitted&&(this.defineEmitted=!0,this.emit("defined",this.exports),this.defineEmitComplete=!0)}}else hasProp(q.defQueueMap,i)||this.fetch()}},callPlugin:function(){var e=this.map,t=e.id,r=a(e.prefix);this.depMaps.push(r),u(r,"defined",bind(this,function(r){var n,o,d,f=getOwn(R,this.map.id),l=this.map.name,h=this.map.parentMap?this.map.parentMap.name:null,m=q.makeRequire(e.parentMap,{enableBuildCallback:!0});return this.map.unnormalized?(r.normalize&&(l=r.normalize(l,function(e){return i(e,h,!0)})||""),o=a(e.prefix+"!"+l,this.map.parentMap,!0),u(o,"defined",bind(this,function(e){this.map.normalizedMap=o,this.init([],function(){return e},null,{enabled:!0,ignore:!0})})),d=getOwn(S,o.id),void(d&&(this.depMaps.push(o),this.events.error&&d.on("error",bind(this,function(e){this.emit("error",e)})),d.enable()))):f?(this.map.url=q.nameToUrl(f),void this.load()):(n=bind(this,function(e){this.init([],function(){return e},null,{enabled:!0})}),n.error=bind(this,function(e){this.inited=!0,this.error=e,e.requireModules=[t],eachProp(S,function(e){0===e.map.id.indexOf(t+"_unnormalized")&&p(e.map.id)}),c(e)}),n.fromText=bind(this,function(i,r){var o=e.name,u=a(o),d=useInteractive;r&&(i=r),d&&(useInteractive=!1),s(u),hasProp(y.config,t)&&(y.config[o]=y.config[t]);try{req.exec(i)}catch(e){return c(makeError("fromtexteval","fromText eval for "+t+" failed: "+e,e,[t]))}d&&(useInteractive=!0),this.depMaps.push(u),q.completeLoad(o),m([o],n)}),void r.load(e.name,m,n,y))})),q.enable(r,this),this.pluginMaps[r.id]=r},enable:function(){k[this.map.id]=this,this.enabled=!0,this.enabling=!0,each(this.depMaps,bind(this,function(e,t){var i,r,n;if("string"==typeof e){if(e=a(e,this.map.isDefine?this.map:this.map.parentMap,!1,!this.skipMap),this.depMaps[t]=e,n=getOwn(E,e.id))return void(this.depExports[t]=n(this));this.depCount+=1,u(e,"defined",bind(this,function(e){this.undefed||(this.defineDep(t,e),this.check())})),this.errback?u(e,"error",bind(this,this.errback)):this.events.error&&u(e,"error",bind(this,function(e){this.emit("error",e)}))}i=e.id,r=S[i],hasProp(E,i)||!r||r.enabled||q.enable(e,this)})),eachProp(this.pluginMaps,bind(this,function(e){var t=getOwn(S,e.id);t&&!t.enabled&&q.enable(e,this)})),this.enabling=!1,this.check()},on:function(e,t){var i=this.events[e];i||(i=this.events[e]=[]),i.push(t)},emit:function(e,t){each(this.events[e],function(e){e(t)}),"error"===e&&delete this.events[e]}},q={config:y,contextName:e,registry:S,defined:j,urlFetched:P,defQueue:O,defQueueMap:{},Module:b,makeModuleMap:a,nextTick:req.nextTick,onError:c,configure:function(e){if(e.baseUrl&&"/"!==e.baseUrl.charAt(e.baseUrl.length-1)&&(e.baseUrl+="/"),"string"==typeof e.urlArgs){var t=e.urlArgs;e.urlArgs=function(e,i){return(i.indexOf("?")===-1?"?":"&")+t}}var i=y.shim,r={paths:!0,bundles:!0,config:!0,map:!0};eachProp(e,function(e,t){r[t]?(y[t]||(y[t]={}),mixin(y[t],e,!0,!0)):y[t]=e}),e.bundles&&eachProp(e.bundles,function(e,t){each(e,function(e){e!==t&&(R[e]=t)})}),e.shim&&(eachProp(e.shim,function(e,t){isArray(e)&&(e={deps:e}),!e.exports&&!e.init||e.exportsFn||(e.exportsFn=q.makeShimExports(e)),i[t]=e}),y.shim=i),e.packages&&each(e.packages,function(e){var t,i;e="string"==typeof e?{name:e}:e,i=e.name,t=e.location,t&&(y.paths[i]=e.location),y.pkgs[i]=e.name+"/"+(e.main||"main").replace(currDirRegExp,"").replace(jsSuffixRegExp,"")}),eachProp(S,function(e,t){e.inited||e.map.unnormalized||(e.map=a(t,null,!0))}),(e.deps||e.callback)&&q.require(e.deps||[],e.callback)},makeShimExports:function(e){function t(){var t;return e.init&&(t=e.init.apply(global,arguments)),t||e.exports&&getGlobal(e.exports)}return t},makeRequire:function(t,n){function o(i,r,u){var d,p,f;return n.enableBuildCallback&&r&&isFunction(r)&&(r.__requireJsBuild=!0),"string"==typeof i?isFunction(r)?c(makeError("requireargs","Invalid require call"),u):t&&hasProp(E,i)?E[i](S[t.id]):req.get?req.get(q,i,t,o):(p=a(i,t,!1,!0),d=p.id,hasProp(j,d)?j[d]:c(makeError("notloaded",'Module name "'+d+'" has not been loaded yet for context: '+e+(t?"":". Use require([])")))):(v(),q.nextTick(function(){v(),f=s(a(null,t)),f.skipMap=n.skipMap,f.init(i,r,u,{enabled:!0}),l()}),o)}return n=n||{},mixin(o,{isBrowser:isBrowser,toUrl:function(e){var r,n=e.lastIndexOf("."),o=e.split("/")[0],a="."===o||".."===o;return n!==-1&&(!a||n>1)&&(r=e.substring(n,e.length),e=e.substring(0,n)),q.nameToUrl(i(e,t&&t.id,!0),r,!0)},defined:function(e){return hasProp(j,a(e,t,!1,!0).id)},specified:function(e){return e=a(e,t,!1,!0).id,hasProp(j,e)||hasProp(S,e)}}),t||(o.undef=function(e){d();var i=a(e,t,!0),n=getOwn(S,e);n.undefed=!0,r(e),delete j[e],delete P[i.url],delete M[e],eachReverse(O,function(t,i){t[0]===e&&O.splice(i,1)}),delete q.defQueueMap[e],n&&(n.events.defined&&(M[e]=n.events),p(e))}),o},enable:function(e){var t=getOwn(S,e.id);t&&s(e).enable()},completeLoad:function(e){var t,i,r,o=getOwn(y.shim,e)||{},a=o.exports;for(d();O.length;){if(i=O.shift(),null===i[0]){if(i[0]=e,t)break;t=!0}else i[0]===e&&(t=!0);h(i)}if(q.defQueueMap={},r=getOwn(S,e),!t&&!hasProp(j,e)&&r&&!r.inited){if(!(!y.enforceDefine||a&&getGlobal(a)))return n(e)?void 0:c(makeError("nodefine","No define call for "+e,null,[e]));h([e,o.deps||[],o.exportsFn])}l()},nameToUrl:function(e,t,i){var r,n,o,a,s,u,c,d=getOwn(y.pkgs,e);if(d&&(e=d),c=getOwn(R,e))return q.nameToUrl(c,t,i);if(req.jsExtRegExp.test(e))s=e+(t||"");else{for(r=y.paths,n=e.split("/"),o=n.length;o>0;o-=1)if(a=n.slice(0,o).join("/"),u=getOwn(r,a)){isArray(u)&&(u=u[0]),n.splice(0,o,u);break}s=n.join("/"),s+=t||(/^data\:|^blob\:|\?/.test(s)||i?"":".js"),s=("/"===s.charAt(0)||s.match(/^[\w\+\.\-]+:/)?"":y.baseUrl)+s}return y.urlArgs&&!/^blob\:/.test(s)?s+y.urlArgs(e,s):s},load:function(e,t){req.load(q,e,t)},execCb:function(e,t,i,r){return t.apply(r,i)},onScriptLoad:function(e){if("load"===e.type||readyRegExp.test((e.currentTarget||e.srcElement).readyState)){interactiveScript=null;var t=g(e);q.completeLoad(t.id)}},onScriptError:function(e){var t=g(e);if(!n(t.id)){var i=[];return eachProp(S,function(e,r){0!==r.indexOf("_@r")&&each(e.depMaps,function(e){if(e.id===t.id)return i.push(r),!0})}),c(makeError("scripterror",'Script error for "'+t.id+(i.length?'", needed by: '+i.join(", "):'"'),e,[t.id]))}}},q.require=q.makeRequire(),q}function getInteractiveScript(){return interactiveScript&&"interactive"===interactiveScript.readyState?interactiveScript:(eachReverse(scripts(),function(e){if("interactive"===e.readyState)return interactiveScript=e}),interactiveScript)}var req,s,head,baseElement,dataMain,src,interactiveScript,currentlyAddingScript,mainScript,subPath,version="2.3.3",commentRegExp=/\/\*[\s\S]*?\*\/|([^:"'=]|^)\/\/.*$/gm,cjsRequireRegExp=/[^.]\s*require\s*\(\s*["']([^'"\s]+)["']\s*\)/g,jsSuffixRegExp=/\.js$/,currDirRegExp=/^\.\//,op=Object.prototype,ostring=op.toString,hasOwn=op.hasOwnProperty,isBrowser=!("undefined"==typeof window||"undefined"==typeof navigator||!window.document),isWebWorker=!isBrowser&&"undefined"!=typeof importScripts,readyRegExp=isBrowser&&"PLAYSTATION 3"===navigator.platform?/^complete$/:/^(complete|loaded)$/,defContextName="_",isOpera="undefined"!=typeof opera&&"[object Opera]"===opera.toString(),contexts={},cfg={},globalDefQueue=[],useInteractive=!1;if("undefined"==typeof define){if("undefined"!=typeof requirejs){if(isFunction(requirejs))return;cfg=requirejs,requirejs=void 0}"undefined"==typeof require||isFunction(require)||(cfg=require,require=void 0),req=requirejs=function(e,t,i,r){var n,o,a=defContextName;return isArray(e)||"string"==typeof e||(o=e,isArray(t)?(e=t,t=i,i=r):e=[]),o&&o.context&&(a=o.context),n=getOwn(contexts,a),n||(n=contexts[a]=req.s.newContext(a)),o&&n.configure(o),n.require(e,t,i)},req.config=function(e){return req(e)},req.nextTick="undefined"!=typeof setTimeout?function(e){setTimeout(e,4)}:function(e){e()},require||(require=req),req.version=version,req.jsExtRegExp=/^\/|:|\?|\.js$/,req.isBrowser=isBrowser,s=req.s={contexts:contexts,newContext:newContext},req({}),each(["toUrl","undef","defined","specified"],function(e){req[e]=function(){var t=contexts[defContextName];return t.require[e].apply(t,arguments)}}),isBrowser&&(head=s.head=document.getElementsByTagName("head")[0],baseElement=document.getElementsByTagName("base")[0],baseElement&&(head=s.head=baseElement.parentNode)),req.onError=defaultOnError,req.createNode=function(e,t,i){var r=e.xhtml?document.createElementNS("http://www.w3.org/1999/xhtml","html:script"):document.createElement("script");return r.type=e.scriptType||"text/javascript",r.charset="utf-8",r.async=!0,r},req.load=function(e,t,i){var r,n=e&&e.config||{};if(isBrowser)return r=req.createNode(n,t,i),r.setAttribute("data-requirecontext",e.contextName),r.setAttribute("data-requiremodule",t),!r.attachEvent||r.attachEvent.toString&&r.attachEvent.toString().indexOf("[native code")<0||isOpera?(r.addEventListener("load",e.onScriptLoad,!1),r.addEventListener("error",e.onScriptError,!1)):(useInteractive=!0,r.attachEvent("onreadystatechange",e.onScriptLoad)),r.src=i,n.onNodeCreated&&n.onNodeCreated(r,n,t,i),currentlyAddingScript=r,baseElement?head.insertBefore(r,baseElement):head.appendChild(r),currentlyAddingScript=null,r;if(isWebWorker)try{setTimeout(function(){},0),importScripts(i),e.completeLoad(t)}catch(r){e.onError(makeError("importscripts","importScripts failed for "+t+" at "+i,r,[t]))}},isBrowser&&!cfg.skipDataMain&&eachReverse(scripts(),function(e){if(head||(head=e.parentNode),dataMain=e.getAttribute("data-main"))return mainScript=dataMain,cfg.baseUrl||mainScript.indexOf("!")!==-1||(src=mainScript.split("/"),mainScript=src.pop(),subPath=src.length?src.join("/")+"/":"./",cfg.baseUrl=subPath),mainScript=mainScript.replace(jsSuffixRegExp,""),req.jsExtRegExp.test(mainScript)&&(mainScript=dataMain),cfg.deps=cfg.deps?cfg.deps.concat(mainScript):[mainScript],!0}),define=function(e,t,i){var r,n;"string"!=typeof e&&(i=t,t=e,e=null),isArray(t)||(i=t,t=null),!t&&isFunction(i)&&(t=[],i.length&&(i.toString().replace(commentRegExp,commentReplace).replace(cjsRequireRegExp,function(e,i){t.push(i)}),t=(1===i.length?["require"]:["require","exports","module"]).concat(t))),useInteractive&&(r=currentlyAddingScript||getInteractiveScript(),r&&(e||(e=r.getAttribute("data-requiremodule")),n=contexts[r.getAttribute("data-requirecontext")])),n?(n.defQueue.push([e,t,i]),n.defQueueMap[e]=!0):globalDefQueue.push([e,t,i])},define.amd={jQuery:!0},req.exec=function(text){return eval(text)},req(cfg)}}(this,"undefined"==typeof setTimeout?void 0:setTimeout);
\ No newline at end of file
/*! Sea.js 3.0.1 | seajs.org/LICENSE.md */
!function(a,b){function c(a){return function(b){return{}.toString.call(b)=="[object "+a+"]"}}function d(){return B++}function e(a){return a.match(E)[0]}function f(a){for(a=a.replace(F,"/"),a=a.replace(H,"$1/");a.match(G);)a=a.replace(G,"/");return a}function g(a){var b=a.length-1,c=a.charCodeAt(b);return 35===c?a.substring(0,b):".js"===a.substring(b-2)||a.indexOf("?")>0||47===c?a:a+".js"}function h(a){var b=v.alias;return b&&x(b[a])?b[a]:a}function i(a){var b=v.paths,c;return b&&(c=a.match(I))&&x(b[c[1]])&&(a=b[c[1]]+c[2]),a}function j(a){var b=v.vars;return b&&a.indexOf("{")>-1&&(a=a.replace(J,function(a,c){return x(b[c])?b[c]:a})),a}function k(a){var b=v.map,c=a;if(b)for(var d=0,e=b.length;e>d;d++){var f=b[d];if(c=z(f)?f(a)||a:a.replace(f[0],f[1]),c!==a)break}return c}function l(a,b){var c,d=a.charCodeAt(0);if(K.test(a))c=a;else if(46===d)c=(b?e(b):v.cwd)+a;else if(47===d){var g=v.cwd.match(L);c=g?g[0]+a.substring(1):a}else c=v.base+a;return 0===c.indexOf("//")&&(c=location.protocol+c),f(c)}function m(a,b){if(!a)return"";a=h(a),a=i(a),a=h(a),a=j(a),a=h(a),a=g(a),a=h(a);var c=l(a,b);return c=h(c),c=k(c)}function n(a){return a.hasAttribute?a.src:a.getAttribute("src",4)}function o(a,b,c,d){var e;try{importScripts(a)}catch(f){e=f}b(e)}function p(a,b,c,d){var e=Z.createElement("script");c&&(e.charset=c),A(d)||e.setAttribute("crossorigin",d),q(e,b,a),e.async=!0,e.src=a,ca=e,ba?aa.insertBefore(e,ba):aa.appendChild(e),ca=null}function q(a,b,c){function d(c){a.onload=a.onerror=a.onreadystatechange=null,v.debug||aa.removeChild(a),a=null,b(c)}var e="onload"in a;e?(a.onload=d,a.onerror=function(){D("error",{uri:c,node:a}),d(!0)}):a.onreadystatechange=function(){/loaded|complete/.test(a.readyState)&&d()}}function r(){if(ca)return ca;if(da&&"interactive"===da.readyState)return da;for(var a=aa.getElementsByTagName("script"),b=a.length-1;b>=0;b--){var c=a[b];if("interactive"===c.readyState)return da=c}}function s(a){function b(){l=a.charAt(k++)}function c(){return/\s/.test(l)}function d(){return'"'==l||"'"==l}function e(){var c=k,d=l,e=a.indexOf(d,c);if(-1==e)k=m;else if("\\"!=a.charAt(e-1))k=e+1;else for(;m>k;)if(b(),"\\"==l)k++;else if(l==d)break;o&&(p.push(a.substring(c,k-1)),o=0)}function f(){for(k--;m>k;)if(b(),"\\"==l)k++;else{if("/"==l)break;if("["==l)for(;m>k;)if(b(),"\\"==l)k++;else if("]"==l)break}}function g(){return/[a-z_$]/i.test(l)}function h(){var b=a.slice(k-1),c=/^[\w$]+/.exec(b)[0];q={"if":1,"for":1,"while":1,"with":1}[c],n={"break":1,"case":1,"continue":1,"debugger":1,"delete":1,"do":1,"else":1,"false":1,"if":1,"in":1,"instanceof":1,"return":1,"typeof":1,"void":1}[c],u="return"==c,s={"instanceof":1,"delete":1,"void":1,"typeof":1,"return":1}.hasOwnProperty(c),o=/^require\s*(?:\/\*[\s\S]*?\*\/\s*)?\(\s*(['"]).+?\1\s*[),]/.test(b),o?(c=/^require\s*(?:\/\*[\s\S]*?\*\/\s*)?\(\s*['"]/.exec(b)[0],k+=c.length-2):k+=/^[\w$]+(?:\s*\.\s*[\w$]+)*/.exec(b)[0].length-1}function i(){return/\d/.test(l)||"."==l&&/\d/.test(a.charAt(k))}function j(){var b=a.slice(k-1),c;c="."==l?/^\.\d+(?:E[+-]?\d*)?\s*/i.exec(b)[0]:/^0x[\da-f]*/i.test(b)?/^0x[\da-f]*\s*/i.exec(b)[0]:/^\d+\.?\d*(?:E[+-]?\d*)?\s*/i.exec(b)[0],k+=c.length-1,n=0}if(-1==a.indexOf("require"))return[];for(var k=0,l,m=a.length,n=1,o=0,p=[],q=0,r=[],s,t=[],u;m>k;)if(b(),c())!u||"\n"!=l&&"\r"!=l||(s=0,u=0);else if(d())e(),n=1,u=0,s=0;else if("/"==l)if(b(),"/"==l)k=a.indexOf("\n",k),-1==k&&(k=a.length);else if("*"==l){var v=a.indexOf("\n",k);k=a.indexOf("*/",k),-1==k?k=m:k+=2,u&&-1!=v&&k>v&&(s=0,u=0)}else n?(f(),n=0,u=0,s=0):(k--,n=1,u=0,s=1);else if(g())h();else if(i())j(),u=0,s=0;else if("("==l)r.push(q),n=1,u=0,s=1;else if(")"==l)n=r.pop(),u=0,s=0;else if("{"==l)u&&(s=1),t.push(s),u=0,n=1;else if("}"==l)s=t.pop(),n=!s,u=0;else{var w=a.charAt(k);";"==l?s=0:"-"==l&&"-"==w||"+"==l&&"+"==w||"="==l&&">"==w?(s=0,k++):s=1,n="]"!=l,u=0}return p}function t(a,b){this.uri=a,this.dependencies=b||[],this.deps={},this.status=0,this._entry=[]}if(!a.seajs){var u=a.seajs={version:"3.0.1"},v=u.data={},w=c("Object"),x=c("String"),y=Array.isArray||c("Array"),z=c("Function"),A=c("Undefined"),B=0,C=v.events={};u.on=function(a,b){var c=C[a]||(C[a]=[]);return c.push(b),u},u.off=function(a,b){if(!a&&!b)return C=v.events={},u;var c=C[a];if(c)if(b)for(var d=c.length-1;d>=0;d--)c[d]===b&&c.splice(d,1);else delete C[a];return u};var D=u.emit=function(a,b){var c=C[a];if(c){c=c.slice();for(var d=0,e=c.length;e>d;d++)c[d](b)}return u},E=/[^?#]*\//,F=/\/\.\//g,G=/\/[^\/]+\/\.\.\//,H=/([^:\/])\/+\//g,I=/^([^\/:]+)(\/.+)$/,J=/{([^{]+)}/g,K=/^\/\/.|:\//,L=/^.*?\/\/.*?\//;u.resolve=m;var M="undefined"==typeof window&&"undefined"!=typeof importScripts&&z(importScripts),N=/^(about|blob):/,O,P,Q=!location.href||N.test(location.href)?"":e(location.href);if(M){var R;try{var S=Error();throw S}catch(T){R=T.stack.split("\n")}R.shift();for(var U,V=/.*?((?:http|https|file)(?::\/{2}[\w]+)(?:[\/|\.]?)(?:[^\s"]*)).*?/i,W=/(.*?):\d+:\d+\)?$/;R.length>0;){var X=R.shift();if(U=V.exec(X),null!=U)break}var Y;if(null!=U)var Y=W.exec(U[1])[1];P=Y,O=e(Y||Q),""===Q&&(Q=O)}else{var Z=document,$=Z.scripts,_=Z.getElementById("seajsnode")||$[$.length-1];P=n(_),O=e(P||Q)}if(M)u.request=o;else{var Z=document,aa=Z.head||Z.getElementsByTagName("head")[0]||Z.documentElement,ba=aa.getElementsByTagName("base")[0],ca;u.request=p}var da,ea=u.cache={},fa,ga={},ha={},ia={},ja=t.STATUS={FETCHING:1,SAVED:2,LOADING:3,LOADED:4,EXECUTING:5,EXECUTED:6,ERROR:7};t.prototype.resolve=function(){for(var a=this,b=a.dependencies,c=[],d=0,e=b.length;e>d;d++)c[d]=t.resolve(b[d],a.uri);return c},t.prototype.pass=function(){for(var a=this,b=a.dependencies.length,c=0;c<a._entry.length;c++){for(var d=a._entry[c],e=0,f=0;b>f;f++){var g=a.deps[a.dependencies[f]];g.status<ja.LOADED&&!d.history.hasOwnProperty(g.uri)&&(d.history[g.uri]=!0,e++,g._entry.push(d),g.status===ja.LOADING&&g.pass())}e>0&&(d.remain+=e-1,a._entry.shift(),c--)}},t.prototype.load=function(){var a=this;if(!(a.status>=ja.LOADING)){a.status=ja.LOADING;var c=a.resolve();D("load",c);for(var d=0,e=c.length;e>d;d++)a.deps[a.dependencies[d]]=t.get(c[d]);if(a.pass(),a._entry.length)return a.onload(),b;var f={},g;for(d=0;e>d;d++)g=ea[c[d]],g.status<ja.FETCHING?g.fetch(f):g.status===ja.SAVED&&g.load();for(var h in f)f.hasOwnProperty(h)&&f[h]()}},t.prototype.onload=function(){var a=this;a.status=ja.LOADED;for(var b=0,c=(a._entry||[]).length;c>b;b++){var d=a._entry[b];0===--d.remain&&d.callback()}delete a._entry},t.prototype.error=function(){var a=this;a.onload(),a.status=ja.ERROR},t.prototype.exec=function(){function a(b){var d=c.deps[b]||t.get(a.resolve(b));if(d.status==ja.ERROR)throw Error("module was broken: "+d.uri);return d.exec()}var c=this;if(c.status>=ja.EXECUTING)return c.exports;if(c.status=ja.EXECUTING,c._entry&&!c._entry.length&&delete c._entry,!c.hasOwnProperty("factory"))return c.non=!0,b;var e=c.uri;a.resolve=function(a){return t.resolve(a,e)},a.async=function(b,c){return t.use(b,c,e+"_async_"+d()),a};var f=c.factory,g=z(f)?f.call(c.exports={},a,c.exports,c):f;return g===b&&(g=c.exports),delete c.factory,c.exports=g,c.status=ja.EXECUTED,D("exec",c),c.exports},t.prototype.fetch=function(a){function c(){u.request(g.requestUri,g.onRequest,g.charset,g.crossorigin)}function d(a){delete ga[h],ha[h]=!0,fa&&(t.save(f,fa),fa=null);var b,c=ia[h];for(delete ia[h];b=c.shift();)a===!0?b.error():b.load()}var e=this,f=e.uri;e.status=ja.FETCHING;var g={uri:f};D("fetch",g);var h=g.requestUri||f;return!h||ha.hasOwnProperty(h)?(e.load(),b):ga.hasOwnProperty(h)?(ia[h].push(e),b):(ga[h]=!0,ia[h]=[e],D("request",g={uri:f,requestUri:h,onRequest:d,charset:z(v.charset)?v.charset(h):v.charset,crossorigin:z(v.crossorigin)?v.crossorigin(h):v.crossorigin}),g.requested||(a?a[g.requestUri]=c:c()),b)},t.resolve=function(a,b){var c={id:a,refUri:b};return D("resolve",c),c.uri||u.resolve(c.id,b)},t.define=function(a,c,d){var e=arguments.length;1===e?(d=a,a=b):2===e&&(d=c,y(a)?(c=a,a=b):c=b),!y(c)&&z(d)&&(c=b===s?[]:s(""+d));var f={id:a,uri:t.resolve(a),deps:c,factory:d};if(!M&&!f.uri&&Z.attachEvent&&b!==r){var g=r();g&&(f.uri=g.src)}D("define",f),f.uri?t.save(f.uri,f):fa=f},t.save=function(a,b){var c=t.get(a);c.status<ja.SAVED&&(c.id=b.id||a,c.dependencies=b.deps||[],c.factory=b.factory,c.status=ja.SAVED,D("save",c))},t.get=function(a,b){return ea[a]||(ea[a]=new t(a,b))},t.use=function(b,c,d){var e=t.get(d,y(b)?b:[b]);e._entry.push(e),e.history={},e.remain=1,e.callback=function(){for(var b=[],d=e.resolve(),f=0,g=d.length;g>f;f++)b[f]=ea[d[f]].exec();c&&c.apply(a,b),delete e.callback,delete e.history,delete e.remain,delete e._entry},e.load()},u.use=function(a,b){return t.use(a,b,v.cwd+"_use_"+d()),u},t.define.cmd={},a.define=t.define,u.Module=t,v.fetchedList=ha,v.cid=d,u.require=function(a){var b=t.get(t.resolve(a));return b.status<ja.EXECUTING&&(b.onload(),b.exec()),b.exports},v.base=O,v.dir=O,v.loader=P,v.cwd=Q,v.charset="utf-8",u.config=function(a){for(var b in a){var c=a[b],d=v[b];if(d&&w(d))for(var e in c)d[e]=c[e];else y(d)?c=d.concat(c):"base"===b&&("/"!==c.slice(-1)&&(c+="/"),c=l(c)),v[b]=c}return D("config",a),u}}}(this);
\ No newline at end of file
var WebRtcStreamer = (function() {
/**
* Interface with WebRTC-streamer API
* @constructor
* @param {string} videoElement - id of the video element tag
* @param {string} srvurl - url of webrtc-streamer (default is current location)
*/
var WebRtcStreamer = function WebRtcStreamer (videoElement, srvurl) {
if (typeof videoElement === "string") {
this.videoElement = document.getElementById(videoElement);
} else {
this.videoElement = videoElement;
}
this.srvurl = srvurl || location.protocol+"//"+window.location.hostname+":"+window.location.port;
this.pc = null;
this.mediaConstraints = { offerToReceiveAudio: true, offerToReceiveVideo: true };
this.iceServers = null;
this.earlyCandidates = [];
}
WebRtcStreamer.prototype._handleHttpErrors = function (response) {
if (!response.ok) {
throw Error(response.statusText);
}
return response;
}
/**
* Connect a WebRTC Stream to videoElement
* @param {string} videourl - id of WebRTC video stream
* @param {string} audiourl - id of WebRTC audio stream
* @param {string} options - options of WebRTC call
* @param {string} stream - local stream to send
* @param {string} prefmime - prefered mime
*/
WebRtcStreamer.prototype.connect = function(videourl, audiourl, options, localstream, prefmime) {
this.disconnect();
// getIceServers is not already received
if (!this.iceServers) {
console.log("Get IceServers");
fetch(this.srvurl + "/api/getIceServers")
.then(this._handleHttpErrors)
.then( (response) => (response.json()) )
.then( (response) => this.onReceiveGetIceServers(response, videourl, audiourl, options, localstream, prefmime))
.catch( (error) => this.onError("getIceServers " + error ))
} else {
this.onReceiveGetIceServers(this.iceServers, videourl, audiourl, options, localstream, prefmime);
}
}
/**
* Disconnect a WebRTC Stream and clear videoElement source
*/
WebRtcStreamer.prototype.disconnect = function() {
if (this.videoElement?.srcObject) {
this.videoElement.srcObject.getTracks().forEach(track => {
track.stop()
this.videoElement.srcObject.removeTrack(track);
});
}
if (this.pc) {
fetch(this.srvurl + "/api/hangup?peerid=" + this.pc.peerid)
.then(this._handleHttpErrors)
.catch( (error) => this.onError("hangup " + error ))
try {
this.pc.close();
}
catch (e) {
console.log ("Failure close peer connection:" + e);
}
this.pc = null;
}
}
WebRtcStreamer.prototype.filterPreferredCodec = function(sdp, prefmime) {
const lines = sdp.split('\n');
const [prefkind, prefcodec] = prefmime.toLowerCase().split('/');
let currentMediaType = null;
let sdpSections = [];
let currentSection = [];
// Group lines into sections
lines.forEach(line => {
if (line.startsWith('m=')) {
if (currentSection.length) {
sdpSections.push(currentSection);
}
currentSection = [line];
} else {
currentSection.push(line);
}
});
sdpSections.push(currentSection);
// Process each section
const processedSections = sdpSections.map(section => {
const firstLine = section[0];
if (!firstLine.startsWith('m=' + prefkind)) {
return section.join('\n');
}
// Get payload types for preferred codec
const rtpLines = section.filter(line => line.startsWith('a=rtpmap:'));
const preferredPayloads = rtpLines
.filter(line => line.toLowerCase().includes(prefcodec))
.map(line => line.split(':')[1].split(' ')[0]);
if (preferredPayloads.length === 0) {
return section.join('\n');
}
// Modify m= line to only include preferred payloads
const mLine = firstLine.split(' ');
const newMLine = [...mLine.slice(0,3), ...preferredPayloads].join(' ');
// Filter related attributes
const filteredLines = section.filter(line => {
if (line === firstLine) return false;
if (line.startsWith('a=rtpmap:')) {
return preferredPayloads.some(payload => line.startsWith(`a=rtpmap:${payload}`));
}
if (line.startsWith('a=fmtp:') || line.startsWith('a=rtcp-fb:')) {
return preferredPayloads.some(payload => line.startsWith(`a=${line.split(':')[0].split('a=')[1]}:${payload}`));
}
return true;
});
return [newMLine, ...filteredLines].join('\n');
});
return processedSections.join('\n');
}
/*
* GetIceServers callback
*/
WebRtcStreamer.prototype.onReceiveGetIceServers = function(iceServers, videourl, audiourl, options, stream, prefmime) {
this.iceServers = iceServers;
this.pcConfig = iceServers || {"iceServers": [] };
try {
this.createPeerConnection();
let callurl = this.srvurl + "/api/call?peerid=" + this.pc.peerid + "&url=" + encodeURIComponent(videourl);
if (audiourl) {
callurl += "&audiourl="+encodeURIComponent(audiourl);
}
if (options) {
callurl += "&options="+encodeURIComponent(options);
}
if (stream) {
this.pc.addStream(stream);
}
// clear early candidates
this.earlyCandidates.length = 0;
// create Offer
this.pc.createOffer(this.mediaConstraints).then((sessionDescription) => {
console.log("Create offer:" + JSON.stringify(sessionDescription));
console.log(`video codecs:${Array.from(new Set(RTCRtpReceiver.getCapabilities("video")?.codecs?.map(codec => codec.mimeType)))}`)
console.log(`audio codecs:${Array.from(new Set(RTCRtpReceiver.getCapabilities("audio")?.codecs?.map(codec => codec.mimeType)))}`)
if (prefmime != undefined) {
//set prefered codec
let [prefkind] = prefmime.split('/');
if (prefkind != "video" && prefkind != "audio") {
prefkind = "video";
prefmime = prefkind + "/" + prefmime;
}
console.log("sdp:" + sessionDescription.sdp);
sessionDescription.sdp = this.filterPreferredCodec(sessionDescription.sdp, prefmime);
console.log("sdp:" + sessionDescription.sdp);
}
this.pc.setLocalDescription(sessionDescription)
.then(() => {
fetch(callurl, { method: "POST", body: JSON.stringify(sessionDescription) })
.then(this._handleHttpErrors)
.then( (response) => (response.json()) )
.catch( (error) => this.onError("call " + error ))
.then( (response) => this.onReceiveCall(response) )
.catch( (error) => this.onError("call " + error ))
}, (error) => {
console.log ("setLocalDescription error:" + JSON.stringify(error));
});
}, (error) => {
alert("Create offer error:" + JSON.stringify(error));
});
} catch (e) {
this.disconnect();
alert("connect error: " + e);
}
}
WebRtcStreamer.prototype.getIceCandidate = function() {
fetch(this.srvurl + "/api/getIceCandidate?peerid=" + this.pc.peerid)
.then(this._handleHttpErrors)
.then( (response) => (response.json()) )
.then( (response) => this.onReceiveCandidate(response))
.catch( (error) => this.onError("getIceCandidate " + error ))
}
/*
* create RTCPeerConnection
*/
WebRtcStreamer.prototype.createPeerConnection = function() {
console.log("createPeerConnection config: " + JSON.stringify(this.pcConfig));
this.pc = new RTCPeerConnection(this.pcConfig);
let pc = this.pc;
pc.peerid = Math.random();
pc.onicecandidate = (evt) => this.onIceCandidate(evt);
pc.onaddstream = (evt) => this.onAddStream(evt);
pc.oniceconnectionstatechange = (evt) => {
console.log("oniceconnectionstatechange state: " + pc.iceConnectionState);
if (this.videoElement) {
if (pc.iceConnectionState === "connected") {
this.videoElement.style.opacity = "1.0";
}
else if (pc.iceConnectionState === "disconnected") {
this.videoElement.style.opacity = "0.25";
}
else if ( (pc.iceConnectionState === "failed") || (pc.iceConnectionState === "closed") ) {
this.videoElement.style.opacity = "0.5";
} else if (pc.iceConnectionState === "new") {
this.getIceCandidate();
}
}
}
pc.ondatachannel = function(evt) {
console.log("remote datachannel created:"+JSON.stringify(evt));
evt.channel.onopen = function () {
console.log("remote datachannel open");
this.send("remote channel openned");
}
evt.channel.onmessage = function (event) {
console.log("remote datachannel recv:"+JSON.stringify(event.data));
}
}
try {
let dataChannel = pc.createDataChannel("ClientDataChannel");
dataChannel.onopen = function() {
console.log("local datachannel open");
this.send("local channel openned");
}
dataChannel.onmessage = function(evt) {
console.log("local datachannel recv:"+JSON.stringify(evt.data));
}
} catch (e) {
console.log("Cannor create datachannel error: " + e);
}
console.log("Created RTCPeerConnnection with config: " + JSON.stringify(this.pcConfig) );
return pc;
}
/*
* RTCPeerConnection IceCandidate callback
*/
WebRtcStreamer.prototype.onIceCandidate = function (event) {
if (event.candidate) {
if (this.pc.currentRemoteDescription) {
this.addIceCandidate(this.pc.peerid, event.candidate);
} else {
this.earlyCandidates.push(event.candidate);
}
}
else {
console.log("End of candidates.");
}
}
WebRtcStreamer.prototype.addIceCandidate = function(peerid, candidate) {
fetch(this.srvurl + "/api/addIceCandidate?peerid="+peerid, { method: "POST", body: JSON.stringify(candidate) })
.then(this._handleHttpErrors)
.then( (response) => (response.json()) )
.then( (response) => {console.log("addIceCandidate ok:" + response)})
.catch( (error) => this.onError("addIceCandidate " + error ))
}
/*
* RTCPeerConnection AddTrack callback
*/
WebRtcStreamer.prototype.onAddStream = function(event) {
console.log("Remote track added:" + JSON.stringify(event));
this.videoElement.srcObject = event.stream;
let promise = this.videoElement.play();
if (promise !== undefined) {
promise.catch((error) => {
console.warn("error:"+error);
this.videoElement.setAttribute("controls", true);
});
}
}
/*
* AJAX /call callback
*/
WebRtcStreamer.prototype.onReceiveCall = function(dataJson) {
console.log("offer: " + JSON.stringify(dataJson));
let descr = new RTCSessionDescription(dataJson);
this.pc.setRemoteDescription(descr).then(() => {
console.log ("setRemoteDescription ok");
while (this.earlyCandidates.length) {
let candidate = this.earlyCandidates.shift();
this.addIceCandidate(this.pc.peerid, candidate);
}
this.getIceCandidate()
}
, (error) => {
console.log ("setRemoteDescription error:" + JSON.stringify(error));
});
}
/*
* AJAX /getIceCandidate callback
*/
WebRtcStreamer.prototype.onReceiveCandidate = function(dataJson) {
console.log("candidate: " + JSON.stringify(dataJson));
if (dataJson) {
for (let i=0; i<dataJson.length; i++) {
let candidate = new RTCIceCandidate(dataJson[i]);
console.log("Adding ICE candidate :" + JSON.stringify(candidate) );
this.pc.addIceCandidate(candidate).then( () => { console.log ("addIceCandidate OK"); }
, (error) => { console.log ("addIceCandidate error:" + JSON.stringify(error)); } );
}
this.pc.addIceCandidate();
}
}
/*
* AJAX callback for Error
*/
WebRtcStreamer.prototype.onError = function(status) {
console.log("onError:" + status);
}
return WebRtcStreamer;
})();
if (typeof window !== 'undefined' && typeof window.document !== 'undefined') {
window.WebRtcStreamer = WebRtcStreamer;
}
if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') {
module.exports = WebRtcStreamer;
}
...@@ -46,9 +46,6 @@ export const getEnvironmentData = async (): Promise<any> => await axios.get('/ho ...@@ -46,9 +46,6 @@ export const getEnvironmentData = async (): Promise<any> => await axios.get('/ho
// 获取在线数据接口 // 获取在线数据接口
export const getOnlineData = async (): Promise<any> => await axios.get('/home/online/data'); export const getOnlineData = async (): Promise<any> => await axios.get('/home/online/data');
// 获取车辆日志列表接口
export const getCarLogList = async (): Promise<any> => await axios.get('home/car/log');
// export const getOnlineAlarmList = async (): Promise<any> => await axios.get('/home/online/alarm/list'); // export const getOnlineAlarmList = async (): Promise<any> => await axios.get('/home/online/alarm/list');
// export const getOnlineAlarmList = async (): Promise<any> => await axios.get('/home/online/alarm/list'); // export const getOnlineAlarmList = async (): Promise<any> => await axios.get('/home/online/alarm/list');
// export const getOnlineAlarmList = async (): Promise<any> => await axios.get('/home/online/alarm/list'); // export const getOnlineAlarmList = async (): Promise<any> => await axios.get('/home/online/alarm/list');
......
...@@ -165,8 +165,7 @@ export const getPointAllPersonApi = async (): Promise<any> => await axios.get(`/ ...@@ -165,8 +165,7 @@ export const getPointAllPersonApi = async (): Promise<any> => await axios.get(`/
// 查询人员轨迹 // 查询人员轨迹
export const getPersonPointApi = async (data:any): Promise<any> => await axios.post(`/person/point/trajectory`,data); export const getPersonPointApi = async (data:any): Promise<any> => await axios.post(`/person/point/trajectory`,data);
// 查询车辆轨迹
export const getCarPointApi = async (data:any): Promise<any> => await axios.post(`/car/point/trajectory`,data);
// ------------------- 越界开采报警接口 ------------------ // ------------------- 越界开采报警接口 ------------------
export const getFencePageApi = async (data:any): Promise<any> => await axios.get(`/fence/log/page?pageNum=${data.pageNum}&pageSize=${data.pageSize}&username=${data.username}&carNumber=${data.carNumber}&startTime=${data.startTime}&endTime=${data.endTime}`); export const getFencePageApi = async (data:any): Promise<any> => await axios.get(`/fence/log/page?pageNum=${data.pageNum}&pageSize=${data.pageSize}&username=${data.username}&carNumber=${data.carNumber}&startTime=${data.startTime}&endTime=${data.endTime}`);
...@@ -177,8 +176,23 @@ export const putFenceeLogApi = async (data:any): Promise<any> => await axios.put ...@@ -177,8 +176,23 @@ export const putFenceeLogApi = async (data:any): Promise<any> => await axios.put
export const delFenceLogApi = async (ids:any): Promise<any> => await axios.delete(`/fence/log/${ids}`,); export const delFenceLogApi = async (ids:any): Promise<any> => await axios.delete(`/fence/log/${ids}`,);
// 大屏卡车位置信息 // 大屏信息
export const getCarPointAllCarApi = async (): Promise<any> => await axios.get(`/car/point/all/car/location`,); export const getCarPointAllCarApi = async (): Promise<any> => await axios.get(`/car/point/all/car/location`);
//
export const getHomeCarApi = async (carNumber:any): Promise<any> => await axios.get(`/home/car/${carNumber}`);
export const getCemeraPointApi = async (): Promise<any> => await axios.get(`/home/camera/point`);
export const getCameraIdApi = async (id:any): Promise<any> => await axios.get(`/home/camera/${id}`);
export const getMonitorPointApi = async (): Promise<any> => await axios.get(`/home/monitor/point`);
export const getMonitorIdApi = async (id:any): Promise<any> => await axios.get(`/home/monitor/${id}`);
// 卡调
export const getCarPointCarNumberApi = async (): Promise<any> => await axios.get(`/car/point/carNumber`,);
// 查询车辆轨迹
export const getCarPointApi = async (data:any): Promise<any> => await axios.post(`/car/point/trajectory`,data);
// 摄像头
export const getPointListApi = async (): Promise<any> => await axios.get(`/cameras/point/list`,);
export function carSpeed(data:any) {
// 路程
let totalDistance = 0;
// 时间
let totalTimeMs = 0;
for (let i = 0; i < data.points.length - 1; i++) {
const point1 = Cesium.Cartesian3.fromDegrees(data.points[i].lon, data.points[i].lat);
const point2 = Cesium.Cartesian3.fromDegrees(data.points[i + 1].lon, data.points[i + 1].lat);
totalDistance += Cesium.Cartesian3.distance(point1, point2);
const time1 = new Date(data.points[i].createTime).getTime();
const time2 = new Date(data.points[i + 1].createTime).getTime();
const timeDiff = Math.abs(time2 - time1); // 使用绝对值确保时间为正
totalTimeMs += timeDiff;
}
const totalTimeHours = totalTimeMs / (1000 * 60 * 60); // 转换为小时
const totalDistanceKm = totalDistance / 1000;
// 平均时速 (公里/小时)
const averageSpeed = totalTimeHours > 0 ? totalDistanceKm / totalTimeHours : 0;
return averageSpeed;
}
\ No newline at end of file
import { AnymatchFn } from 'vite';
import { ref } from 'vue';
import { useMessage } from 'naive-ui';
import { log } from 'echarts/types/src/util/log.js';
import { cesiumToLongitudeAndLatitude } from './coordinateUtil';
const message = useMessage();
const line = ref<any>(null);
let modelExtiti: any = null;
const isOver = false;
// 创建自定义圆形大头针的函数(使用 Canvas 动态生成)
export function createCustomPinImage() {
const canvas = document.createElement('canvas');
const size = 48; // 图标大小
canvas.width = size;
canvas.height = size * 2; // 包括杆子部分
const context = canvas.getContext('2d');
// 绘制红色圆圈(带白边)
context.beginPath();
context.arc(size / 2, size / 2, size / 2 - 4, 0, 2 * Math.PI); // 圆圈
context.fillStyle = 'white'; // 白色边框
context.fill();
context.beginPath();
context.arc(size / 2, size / 2, size / 2 - 8, 0, 2 * Math.PI); // 红色填充
context.fillStyle = 'red';
context.fill();
// 绘制杆子(白色)
context.fillStyle = 'white';
context.fillRect(size / 2 - 2, size, 4, size); // 杆子从圆圈底部向下延伸
return canvas.toDataURL('image/png'); // 返回 Base64 编码的图片
}
export function deletePin(viewer: any, data: any) {
viewer.entities.remove(data.pin);
}
export function deletePins(viewer: any, data: any) {
for (let i = 0; i < data.length; i++) {
viewer.entities.remove(data[i].pin);
}
}
export async function getElevationFromRays(cartographic: any, viewer: any) {
let ellipsoid;
let startPoint;
let surfaceNormal;
let direction;
let ray;
return new Promise(resolve => {
ellipsoid = viewer.scene.globe.ellipsoid;
startPoint = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, 200);
surfaceNormal = viewer.scene.globe.ellipsoid.geodeticSurfaceNormal(startPoint);
direction = Cesium.Cartesian3.negate(surfaceNormal, new Cesium.Cartesian3());
ray = new Cesium.Ray(startPoint, direction);
const intersection = viewer.scene.pickFromRay(ray);
if (intersection) {
const cartographicPosition = Cesium.Cartographic.fromCartesian(intersection.position);
resolve(cartographicPosition.height); // 返回检测到的高程
} else {
// 如果没有检测到交点,返回椭球面高度(0)或其他默认值
resolve(0);
}
});
}
export async function getElevationFromRay(cartographic: any, viewer: any) {
let ellipsoid;
let startPoint;
let surfaceNormal;
let direction;
let ray;
return new Promise((resolve, reject) => {
ellipsoid = viewer.scene.globe.ellipsoid;
startPoint = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, 200);
surfaceNormal = viewer.scene.globe.ellipsoid.geodeticSurfaceNormal(startPoint);
direction = Cesium.Cartesian3.negate(surfaceNormal, new Cesium.Cartesian3());
ray = new Cesium.Ray(startPoint, direction);
const intersection = viewer.scene.pickFromRay(ray);
if (intersection) {
const cartographicPosition = Cesium.Cartographic.fromCartesian(intersection.position);
resolve(cartographicPosition.height); // 返回高程
} else {
reject('未检测到交点');
}
});
}
// 创建红色线
export function createPolyLine(positions: any, viewer: any) {
line.value = viewer.entities.add({
name: 'polyline',
polyline: {
show: true, // 显示折线
positions, // 折线顶点的位置数组
material: Cesium.Color.fromCssColorString(`rgb(212, 16, 16)`), // 折线颜色
width: 3, // 折线宽度
clampToGround: true, // 将折线贴地
zIndex: 92, // 折线层级索引
classificationType: Cesium.ClassificationType.BOTH, // 折线分类类型
heightReference: Cesium.HeightReference.NONE
}
});
return line.value;
}
export function cleanLine(viewer: any, positions: any) {
viewer.entities.remove(line.value);
viewer.entities.remove(positions);
}
export function createModel(positions: any, viewer: any) {
if (positions.length == 0) {
message.error('没有数据');
return;
}
const url = '/src/assets/imgs/car.glb';
const startPoint = positions[0];
if (modelExtiti) {
viewer.entities.remove(modelExtiti);
}
const entityOptions = {
position: startPoint,
orientation: Cesium.Transforms.headingPitchRollQuaternion(startPoint, new Cesium.HeadingPitchRoll(0, 0, 0)),
model: {
uri: url,
scale: 1.0,
minimumPixelSize: 100,
disableDepthTestDistance: 'infinite',
runAnimations: true
}
};
// 创建并添加实体
modelExtiti = viewer.entities.add(entityOptions);
return modelExtiti;
}
// 辅助函数:开始车辆移动动画
function densifyPoints(positions: any[], stepSize: number = 2.0) {
if (positions.length < 2) return positions;
const densified: any[] = [];
for (let i = 0; i < positions.length - 1; i++) {
const start = positions[i];
const end = positions[i + 1];
// 计算两点间距离
const distance = Cesium.Cartesian3.distance(start, end);
// 放入起始点
densified.push(start);
// 如果距离过大,计算需要插入多少个点
if (distance > stepSize) {
const count = Math.ceil(distance / stepSize);
for (let j = 1; j < count; j++) {
// 线性插值计算中间点
const t = j / count;
const newPoint = Cesium.Cartesian3.lerp(start, end, t, new Cesium.Cartesian3());
densified.push(newPoint);
}
}
}
// 别忘了把最后一个点放进去
densified.push(positions[positions.length - 1]);
return densified;
}
export async function startVehicleMovement(viewer: any, totalDuration: number) {
// 1. 重置
viewer.clock.currentTime = Cesium.JulianDate.now();
viewer.clock.shouldAnimate = false;
viewer.clock.multiplier = 1;
const trail = line.value;
if (!trail || !trail.polyline || !trail.polyline.positions) return;
const rawCoordinates = trail.polyline.positions.getValue();
if (!rawCoordinates || rawCoordinates.length === 0) return;
// =========================================================
// ✅ 核心改进 1:路径加密
// 先把只有几个顶点的折线,变成几百个密集的点
// 这样每个点都能去探测模型高度,车子就能贴合起伏了
// =========================================================
const denseCoordinates = densifyPoints(rawCoordinates, 2.0); // 每隔2米插入一个点
let clampedPositions: any[] = [];
try {
// =========================================================
// ✅ 核心改进 2:批量计算高度
// 现在计算的是加密后那几百个点的高度
// =========================================================
// 提示:clampToHeightMostDetailed 支持的点的数量有限,
// 如果路线非常非常长(几十公里),可能需要分段计算,但一般几千个点没问题。
const updatedPositions = await viewer.scene.clampToHeightMostDetailed(denseCoordinates);
clampedPositions = updatedPositions.map((pos: any) => {
const cartographic = Cesium.Cartographic.fromCartesian(pos);
// 💡 稍微抬高 0.5 - 1.0 米,防止车轮半截入土
return Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, cartographic.height + 0.8);
});
} catch (error) {
console.warn('高度贴合计算失败或部分失败:', error);
clampedPositions = denseCoordinates;
}
// =========================================================
// 下面的逻辑和之前一样,构建 SampledProperty
// =========================================================
const positionProperty = new Cesium.SampledPositionProperty();
let totalDistance = 0;
for (let i = 0; i < clampedPositions.length - 1; i++) {
totalDistance += Cesium.Cartesian3.distance(clampedPositions[i], clampedPositions[i + 1]);
}
let accumulatedTime = 0;
positionProperty.addSample(viewer.clock.currentTime, clampedPositions[0]);
for (let i = 1; i < clampedPositions.length; i++) {
const segmentDistance = Cesium.Cartesian3.distance(clampedPositions[i - 1], clampedPositions[i]);
const segmentDuration = (segmentDistance / totalDistance) * totalDuration;
accumulatedTime += segmentDuration;
const time = Cesium.JulianDate.addSeconds(viewer.clock.currentTime, accumulatedTime, new Cesium.JulianDate());
positionProperty.addSample(time, clampedPositions[i]);
}
// 因为点很密集,线性插值(LinearApproximation)其实比 Hermite 更稳,不容易出现“过冲”导致的抖动
// 当然 Hermite 也可以,看效果决定
positionProperty.setInterpolationOptions({
interpolationDegree: 1,
interpolationAlgorithm: Cesium.LinearApproximation
});
if (!modelExtiti) return;
modelExtiti.position = positionProperty;
// 姿态计算
const velocityOrientation = new Cesium.VelocityOrientationProperty(positionProperty);
const headingOffset = Cesium.Math.toRadians(90); // 按需调整
modelExtiti.orientation = new Cesium.CallbackProperty((time: any) => {
const velocityQuaternion = velocityOrientation.getValue(time);
if (!velocityQuaternion) return undefined;
const rotation = Cesium.Quaternion.fromAxisAngle(Cesium.Cartesian3.UNIT_Z, headingOffset);
return Cesium.Quaternion.multiply(velocityQuaternion, rotation, new Cesium.Quaternion());
}, false);
viewer.clock.shouldAnimate = true;
// 结束清理逻辑
const stopTime = Cesium.JulianDate.addSeconds(viewer.clock.currentTime, totalDuration, new Cesium.JulianDate());
const removeListener = viewer.clock.onTick.addEventListener((clock: any) => {
if (Cesium.JulianDate.compare(clock.currentTime, stopTime) >= 0) {
viewer.clock.shouldAnimate = false;
viewer.clock.currentTime = Cesium.JulianDate.now();
// 可以在这重置位置
// modelExtiti.position = clampedPositions[0];
removeListener();
}
});
}
...@@ -94,7 +94,6 @@ export async function getElevationFromRay(cartographic: any, viewer: any) { ...@@ -94,7 +94,6 @@ export async function getElevationFromRay(cartographic: any, viewer: any) {
// 创建红色线 // 创建红色线
export function createPolyLine(positions: any, viewer: any) { export function createPolyLine(positions: any, viewer: any) {
console.log(positions);
line.value = viewer.entities.add({ line.value = viewer.entities.add({
name: 'polyline', name: 'polyline',
polyline: { polyline: {
...@@ -182,39 +181,16 @@ function densifyPoints(positions: any[], stepSize: number = 2.0) { ...@@ -182,39 +181,16 @@ function densifyPoints(positions: any[], stepSize: number = 2.0) {
return densified; return densified;
} }
export async function startVehicleMovement(viewer: any, totalDuration: number) { export async function createNewPositionHeight(position: any, viewer: any) {
// 1. 重置 const denseCoordinates = densifyPoints(position, 10.0); // 每隔2米插入一个点
viewer.clock.currentTime = Cesium.JulianDate.now();
viewer.clock.shouldAnimate = false;
viewer.clock.multiplier = 1;
const trail = line.value;
if (!trail || !trail.polyline || !trail.polyline.positions) return;
const rawCoordinates = trail.polyline.positions.getValue();
if (!rawCoordinates || rawCoordinates.length === 0) return;
// =========================================================
// ✅ 核心改进 1:路径加密
// 先把只有几个顶点的折线,变成几百个密集的点
// 这样每个点都能去探测模型高度,车子就能贴合起伏了
// =========================================================
const denseCoordinates = densifyPoints(rawCoordinates, 2.0); // 每隔2米插入一个点
let clampedPositions: any[] = []; let clampedPositions: any[] = [];
try { try {
// =========================================================
// ✅ 核心改进 2:批量计算高度
// 现在计算的是加密后那几百个点的高度
// =========================================================
// 提示:clampToHeightMostDetailed 支持的点的数量有限,
// 如果路线非常非常长(几十公里),可能需要分段计算,但一般几千个点没问题。
const updatedPositions = await viewer.scene.clampToHeightMostDetailed(denseCoordinates); const updatedPositions = await viewer.scene.clampToHeightMostDetailed(denseCoordinates);
clampedPositions = updatedPositions.map((pos: any) => { clampedPositions = updatedPositions.map((pos: any) => {
const cartographic = Cesium.Cartographic.fromCartesian(pos); const cartographic = Cesium.Cartographic.fromCartesian(pos);
// 💡 稍微抬高 0.5 - 1.0 米,防止车轮半截入土
return Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, cartographic.height + 0.8); return Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, cartographic.height + 0.8);
}); });
} catch (error) { } catch (error) {
...@@ -222,6 +198,22 @@ export async function startVehicleMovement(viewer: any, totalDuration: number) { ...@@ -222,6 +198,22 @@ export async function startVehicleMovement(viewer: any, totalDuration: number) {
clampedPositions = denseCoordinates; clampedPositions = denseCoordinates;
} }
return clampedPositions;
}
export async function startVehicleMovement(viewer: any, totalDuration: number) {
// 1. 重置
viewer.clock.currentTime = Cesium.JulianDate.now();
viewer.clock.shouldAnimate = false;
viewer.clock.multiplier = 1;
const trail = line.value;
if (!trail || !trail.polyline || !trail.polyline.positions) return;
const rawCoordinates = trail.polyline.positions.getValue();
if (!rawCoordinates || rawCoordinates.length === 0) return;
// ========================================================= // =========================================================
// 下面的逻辑和之前一样,构建 SampledProperty // 下面的逻辑和之前一样,构建 SampledProperty
// ========================================================= // =========================================================
...@@ -229,20 +221,21 @@ export async function startVehicleMovement(viewer: any, totalDuration: number) { ...@@ -229,20 +221,21 @@ export async function startVehicleMovement(viewer: any, totalDuration: number) {
const positionProperty = new Cesium.SampledPositionProperty(); const positionProperty = new Cesium.SampledPositionProperty();
let totalDistance = 0; let totalDistance = 0;
for (let i = 0; i < clampedPositions.length - 1; i++) { for (let i = 0; i < rawCoordinates.length - 1; i++) {
totalDistance += Cesium.Cartesian3.distance(clampedPositions[i], clampedPositions[i + 1]); totalDistance += Cesium.Cartesian3.distance(rawCoordinates[i], rawCoordinates[i + 1]);
} }
let accumulatedTime = 0; let accumulatedTime = 0;
positionProperty.addSample(viewer.clock.currentTime, clampedPositions[0]); positionProperty.addSample(viewer.clock.currentTime, rawCoordinates[0]);
for (let i = 1; i < clampedPositions.length; i++) { for (let i = 1; i < rawCoordinates.length; i++) {
const segmentDistance = Cesium.Cartesian3.distance(clampedPositions[i - 1], clampedPositions[i]); const segmentDistance = Cesium.Cartesian3.distance(rawCoordinates[i - 1], rawCoordinates[i]);
const segmentDuration = (segmentDistance / totalDistance) * totalDuration; const segmentDuration = (segmentDistance / totalDistance) * totalDuration;
accumulatedTime += segmentDuration; accumulatedTime += segmentDuration;
const time = Cesium.JulianDate.addSeconds(viewer.clock.currentTime, accumulatedTime, new Cesium.JulianDate()); const time = Cesium.JulianDate.addSeconds(viewer.clock.currentTime, accumulatedTime, new Cesium.JulianDate());
positionProperty.addSample(time, clampedPositions[i]); positionProperty.addSample(time, rawCoordinates[i]);
} }
// 因为点很密集,线性插值(LinearApproximation)其实比 Hermite 更稳,不容易出现“过冲”导致的抖动 // 因为点很密集,线性插值(LinearApproximation)其实比 Hermite 更稳,不容易出现“过冲”导致的抖动
......
import { AnymatchFn } from 'vite';
import { ref } from 'vue';
import { useMessage } from 'naive-ui';
import { log } from 'echarts/types/src/util/log.js';
import { cesiumToLongitudeAndLatitude } from './coordinateUtil';
const message = useMessage();
const line = ref<any>(null);
let modelExtiti: any = null;
const isOver = false;
// 创建自定义圆形大头针的函数(使用 Canvas 动态生成)
export function createCustomPinImage() {
const canvas = document.createElement('canvas');
const size = 48; // 图标大小
canvas.width = size;
canvas.height = size * 2; // 包括杆子部分
const context = canvas.getContext('2d');
// 绘制红色圆圈(带白边)
context.beginPath();
context.arc(size / 2, size / 2, size / 2 - 4, 0, 2 * Math.PI); // 圆圈
context.fillStyle = 'white'; // 白色边框
context.fill();
context.beginPath();
context.arc(size / 2, size / 2, size / 2 - 8, 0, 2 * Math.PI); // 红色填充
context.fillStyle = 'red';
context.fill();
// 绘制杆子(白色)
context.fillStyle = 'white';
context.fillRect(size / 2 - 2, size, 4, size); // 杆子从圆圈底部向下延伸
return canvas.toDataURL('image/png'); // 返回 Base64 编码的图片
}
export function deletePin(viewer: any, data: any) {
viewer.entities.remove(data.pin);
}
export function deletePins(viewer: any, data: any) {
for (let i = 0; i < data.length; i++) {
viewer.entities.remove(data[i].pin);
}
}
export async function getElevationFromRays(cartographic: any, viewer: any) {
let ellipsoid;
let startPoint;
let surfaceNormal;
let direction;
let ray;
return new Promise(resolve => {
ellipsoid = viewer.scene.globe.ellipsoid;
startPoint = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, 200);
surfaceNormal = viewer.scene.globe.ellipsoid.geodeticSurfaceNormal(startPoint);
direction = Cesium.Cartesian3.negate(surfaceNormal, new Cesium.Cartesian3());
ray = new Cesium.Ray(startPoint, direction);
const intersection = viewer.scene.pickFromRay(ray);
if (intersection) {
const cartographicPosition = Cesium.Cartographic.fromCartesian(intersection.position);
resolve(cartographicPosition.height); // 返回检测到的高程
} else {
// 如果没有检测到交点,返回椭球面高度(0)或其他默认值
resolve(0);
}
});
}
export async function getElevationFromRay(cartographic: any, viewer: any) {
let ellipsoid;
let startPoint;
let surfaceNormal;
let direction;
let ray;
return new Promise((resolve, reject) => {
ellipsoid = viewer.scene.globe.ellipsoid;
startPoint = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, 200);
surfaceNormal = viewer.scene.globe.ellipsoid.geodeticSurfaceNormal(startPoint);
direction = Cesium.Cartesian3.negate(surfaceNormal, new Cesium.Cartesian3());
ray = new Cesium.Ray(startPoint, direction);
const intersection = viewer.scene.pickFromRay(ray);
if (intersection) {
const cartographicPosition = Cesium.Cartographic.fromCartesian(intersection.position);
resolve(cartographicPosition.height); // 返回高程
} else {
reject('未检测到交点');
}
});
}
// 创建红色线
export function createPolyLine(positions: any, viewer: any) {
console.log(positions);
line.value = viewer.entities.add({
name: 'polyline',
polyline: {
show: true, // 显示折线
positions, // 折线顶点的位置数组
material: Cesium.Color.fromCssColorString(`rgb(212, 16, 16)`), // 折线颜色
width: 3, // 折线宽度
clampToGround: true, // 将折线贴地
zIndex: 92, // 折线层级索引
classificationType: Cesium.ClassificationType.BOTH, // 折线分类类型
heightReference: Cesium.HeightReference.NONE
}
});
return line.value;
}
export function cleanLine(viewer: any, positions: any) {
viewer.entities.remove(line.value);
viewer.entities.remove(positions);
}
export function createModel(positions: any, viewer: any) {
if (positions.length == 0) {
message.error('没有数据');
return;
}
const url = '/src/assets/imgs/person1.glb';
const startPoint = positions[0];
if (modelExtiti) {
viewer.entities.remove(modelExtiti);
}
const entityOptions = {
position: startPoint,
orientation: Cesium.Transforms.headingPitchRollQuaternion(startPoint, new Cesium.HeadingPitchRoll(0, 0, 0)),
model: {
uri: url,
scale: 1.0,
minimumPixelSize: 100,
disableDepthTestDistance: 'infinite',
runAnimations: true
}
};
// 创建并添加实体
modelExtiti = viewer.entities.add(entityOptions);
return modelExtiti;
}
// 辅助函数:开始车辆移动动画
function densifyPoints(positions: any[], stepSize: number = 2.0) {
if (positions.length < 2) return positions;
const densified: any[] = [];
for (let i = 0; i < positions.length - 1; i++) {
const start = positions[i];
const end = positions[i + 1];
// 计算两点间距离
const distance = Cesium.Cartesian3.distance(start, end);
// 放入起始点
densified.push(start);
// 如果距离过大,计算需要插入多少个点
if (distance > stepSize) {
const count = Math.ceil(distance / stepSize);
for (let j = 1; j < count; j++) {
// 线性插值计算中间点
const t = j / count;
const newPoint = Cesium.Cartesian3.lerp(start, end, t, new Cesium.Cartesian3());
densified.push(newPoint);
}
}
}
// 别忘了把最后一个点放进去
densified.push(positions[positions.length - 1]);
return densified;
}
export async function startVehicleMovement(viewer: any, totalDuration: number) {
// 1. 重置
viewer.clock.currentTime = Cesium.JulianDate.now();
viewer.clock.shouldAnimate = false;
viewer.clock.multiplier = 1;
const trail = line.value;
if (!trail || !trail.polyline || !trail.polyline.positions) return;
const rawCoordinates = trail.polyline.positions.getValue();
if (!rawCoordinates || rawCoordinates.length === 0) return;
// =========================================================
// ✅ 核心改进 1:路径加密
// 先把只有几个顶点的折线,变成几百个密集的点
// 这样每个点都能去探测模型高度,车子就能贴合起伏了
// =========================================================
const denseCoordinates = densifyPoints(rawCoordinates, 2.0); // 每隔2米插入一个点
let clampedPositions: any[] = [];
try {
// =========================================================
// ✅ 核心改进 2:批量计算高度
// 现在计算的是加密后那几百个点的高度
// =========================================================
// 提示:clampToHeightMostDetailed 支持的点的数量有限,
// 如果路线非常非常长(几十公里),可能需要分段计算,但一般几千个点没问题。
const updatedPositions = await viewer.scene.clampToHeightMostDetailed(denseCoordinates);
clampedPositions = updatedPositions.map((pos: any) => {
const cartographic = Cesium.Cartographic.fromCartesian(pos);
// 💡 稍微抬高 0.5 - 1.0 米,防止车轮半截入土
return Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, cartographic.height + 0.8);
});
} catch (error) {
console.warn('高度贴合计算失败或部分失败:', error);
clampedPositions = denseCoordinates;
}
// =========================================================
// 下面的逻辑和之前一样,构建 SampledProperty
// =========================================================
const positionProperty = new Cesium.SampledPositionProperty();
let totalDistance = 0;
for (let i = 0; i < clampedPositions.length - 1; i++) {
totalDistance += Cesium.Cartesian3.distance(clampedPositions[i], clampedPositions[i + 1]);
}
let accumulatedTime = 0;
positionProperty.addSample(viewer.clock.currentTime, clampedPositions[0]);
for (let i = 1; i < clampedPositions.length; i++) {
const segmentDistance = Cesium.Cartesian3.distance(clampedPositions[i - 1], clampedPositions[i]);
const segmentDuration = (segmentDistance / totalDistance) * totalDuration;
accumulatedTime += segmentDuration;
const time = Cesium.JulianDate.addSeconds(viewer.clock.currentTime, accumulatedTime, new Cesium.JulianDate());
positionProperty.addSample(time, clampedPositions[i]);
}
// 因为点很密集,线性插值(LinearApproximation)其实比 Hermite 更稳,不容易出现“过冲”导致的抖动
// 当然 Hermite 也可以,看效果决定
positionProperty.setInterpolationOptions({
interpolationDegree: 1,
interpolationAlgorithm: Cesium.LinearApproximation
});
if (!modelExtiti) return;
modelExtiti.position = positionProperty;
// 姿态计算
const velocityOrientation = new Cesium.VelocityOrientationProperty(positionProperty);
const headingOffset = Cesium.Math.toRadians(0); // 按需调整
modelExtiti.orientation = new Cesium.CallbackProperty((time: any) => {
const velocityQuaternion = velocityOrientation.getValue(time);
if (!velocityQuaternion) return undefined;
const rotation = Cesium.Quaternion.fromAxisAngle(Cesium.Cartesian3.UNIT_Z, headingOffset);
return Cesium.Quaternion.multiply(velocityQuaternion, rotation, new Cesium.Quaternion());
}, false);
viewer.clock.shouldAnimate = true;
// 结束清理逻辑
const stopTime = Cesium.JulianDate.addSeconds(viewer.clock.currentTime, totalDuration, new Cesium.JulianDate());
const removeListener = viewer.clock.onTick.addEventListener((clock: any) => {
if (Cesium.JulianDate.compare(clock.currentTime, stopTime) >= 0) {
viewer.clock.shouldAnimate = false;
viewer.clock.currentTime = Cesium.JulianDate.now();
// 可以在这重置位置
// modelExtiti.position = clampedPositions[0];
removeListener();
}
});
}
...@@ -94,7 +94,6 @@ export async function getElevationFromRay(cartographic: any, viewer: any) { ...@@ -94,7 +94,6 @@ export async function getElevationFromRay(cartographic: any, viewer: any) {
// 创建红色线 // 创建红色线
export function createPolyLine(positions: any, viewer: any) { export function createPolyLine(positions: any, viewer: any) {
console.log(positions);
line.value = viewer.entities.add({ line.value = viewer.entities.add({
name: 'polyline', name: 'polyline',
polyline: { polyline: {
...@@ -119,11 +118,11 @@ export function cleanLine(viewer: any, positions: any) { ...@@ -119,11 +118,11 @@ export function cleanLine(viewer: any, positions: any) {
export function createModel(positions: any, viewer: any) { export function createModel(positions: any, viewer: any) {
if (positions.length == 0) { if (positions.length == 0) {
message.error('没有数据'); message.error('这个时间点没有数据');
return; return;
} }
const url = '/src/assets/imgs/person1.glb'; const url = '/src/assets/imgs/person2.glb';
const startPoint = positions[0]; const startPoint = positions[0];
if (modelExtiti) { if (modelExtiti) {
...@@ -182,46 +181,39 @@ function densifyPoints(positions: any[], stepSize: number = 2.0) { ...@@ -182,46 +181,39 @@ function densifyPoints(positions: any[], stepSize: number = 2.0) {
return densified; return densified;
} }
export async function startVehicleMovement(viewer: any, totalDuration: number) { export async function createNewPositionHeight(position: any, viewer: any) {
// 1. 重置 const denseCoordinates = densifyPoints(position, 20.0); // 每隔2米插入一个点
viewer.clock.currentTime = Cesium.JulianDate.now();
viewer.clock.shouldAnimate = false;
viewer.clock.multiplier = 1;
const trail = line.value;
if (!trail || !trail.polyline || !trail.polyline.positions) return;
const rawCoordinates = trail.polyline.positions.getValue();
if (!rawCoordinates || rawCoordinates.length === 0) return;
// =========================================================
// ✅ 核心改进 1:路径加密
// 先把只有几个顶点的折线,变成几百个密集的点
// 这样每个点都能去探测模型高度,车子就能贴合起伏了
// =========================================================
const denseCoordinates = densifyPoints(rawCoordinates, 2.0); // 每隔2米插入一个点
let clampedPositions: any[] = []; let clampedPositions: any[] = [];
try { try {
// =========================================================
// ✅ 核心改进 2:批量计算高度
// 现在计算的是加密后那几百个点的高度
// =========================================================
// 提示:clampToHeightMostDetailed 支持的点的数量有限,
// 如果路线非常非常长(几十公里),可能需要分段计算,但一般几千个点没问题。
const updatedPositions = await viewer.scene.clampToHeightMostDetailed(denseCoordinates); const updatedPositions = await viewer.scene.clampToHeightMostDetailed(denseCoordinates);
clampedPositions = updatedPositions.map((pos: any) => { clampedPositions = updatedPositions.map((pos: any) => {
const cartographic = Cesium.Cartographic.fromCartesian(pos); const cartographic = Cesium.Cartographic.fromCartesian(pos);
// 💡 稍微抬高 0.5 - 1.0 米,防止车轮半截入土 return Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, cartographic.height + 6);
return Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, cartographic.height + 0.8);
}); });
} catch (error) { } catch (error) {
console.warn('高度贴合计算失败或部分失败:', error); console.warn('高度贴合计算失败或部分失败:', error);
clampedPositions = denseCoordinates; clampedPositions = denseCoordinates;
} }
return clampedPositions;
}
export async function startVehicleMovement(viewer: any, totalDuration: number) {
// 1. 重置
viewer.clock.currentTime = Cesium.JulianDate.now();
viewer.clock.shouldAnimate = false;
viewer.clock.multiplier = 1;
const trail = line.value;
if (!trail || !trail.polyline || !trail.polyline.positions) return;
const rawCoordinates = trail.polyline.positions.getValue();
if (!rawCoordinates || rawCoordinates.length === 0) return;
// ========================================================= // =========================================================
// 下面的逻辑和之前一样,构建 SampledProperty // 下面的逻辑和之前一样,构建 SampledProperty
// ========================================================= // =========================================================
...@@ -229,20 +221,21 @@ export async function startVehicleMovement(viewer: any, totalDuration: number) { ...@@ -229,20 +221,21 @@ export async function startVehicleMovement(viewer: any, totalDuration: number) {
const positionProperty = new Cesium.SampledPositionProperty(); const positionProperty = new Cesium.SampledPositionProperty();
let totalDistance = 0; let totalDistance = 0;
for (let i = 0; i < clampedPositions.length - 1; i++) { for (let i = 0; i < rawCoordinates.length - 1; i++) {
totalDistance += Cesium.Cartesian3.distance(clampedPositions[i], clampedPositions[i + 1]); totalDistance += Cesium.Cartesian3.distance(rawCoordinates[i], rawCoordinates[i + 1]);
} }
let accumulatedTime = 0; let accumulatedTime = 0;
positionProperty.addSample(viewer.clock.currentTime, clampedPositions[0]); positionProperty.addSample(viewer.clock.currentTime, rawCoordinates[0]);
for (let i = 1; i < clampedPositions.length; i++) { for (let i = 1; i < rawCoordinates.length; i++) {
const segmentDistance = Cesium.Cartesian3.distance(clampedPositions[i - 1], clampedPositions[i]); const segmentDistance = Cesium.Cartesian3.distance(rawCoordinates[i - 1], rawCoordinates[i]);
const segmentDuration = (segmentDistance / totalDistance) * totalDuration; const segmentDuration = (segmentDistance / totalDistance) * totalDuration;
accumulatedTime += segmentDuration; accumulatedTime += segmentDuration;
const time = Cesium.JulianDate.addSeconds(viewer.clock.currentTime, accumulatedTime, new Cesium.JulianDate()); const time = Cesium.JulianDate.addSeconds(viewer.clock.currentTime, accumulatedTime, new Cesium.JulianDate());
positionProperty.addSample(time, clampedPositions[i]); positionProperty.addSample(time, rawCoordinates[i]);
} }
// 因为点很密集,线性插值(LinearApproximation)其实比 Hermite 更稳,不容易出现“过冲”导致的抖动 // 因为点很密集,线性插值(LinearApproximation)其实比 Hermite 更稳,不容易出现“过冲”导致的抖动
......
import { ref } from 'vue';
import { getPointAllPersonApi } from '@/api';
import bluePersonIcon from '@/assets/blueperson.png';
import { getElevationFromRays } from '../cesiumUtil';
let personEntity: any;
const iconEntities = ref<any[]>([]);
const pins: any = [];
// 点位图标
export async function iconPoint(viewer: any, pins: any) {
// // 批量移除实体
iconEntities.value.forEach(item => {
viewer.entities.remove(item.labelExtity);
viewer.entities.remove(item.entity);
});
for (const item of pins) {
if (item.entity) {
viewer.entities.remove(item.entity);
}
const cartographic = Cesium.Cartographic.fromDegrees(item.position.lon, item.position.lat);
const height = await getElevationFromRays(cartographic, viewer);
const cartesian = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, height);
item.entity = viewer.entities.add({
position: cartesian,
billboard: {
image: item.image,
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
scale: 0.5,
heightReference: Cesium.HeightReference.RELATIVE_TO_GROUND
},
properties: {
type: item.type
}
});
allEntities.push(item.entity);
const entity = viewer.entities.add({
position: cartesian,
billboard: {
image: new URL('../../../assets/titlePerson.png', import.meta.url).href,
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
scale: 0.5,
pixelOffset: new Cesium.Cartesian2(0, -30), // 位置在图标上方
heightReference: Cesium.HeightReference.RELATIVE_TO_GROUND
},
properties: {
type: item.type
}
});
entity.billboard.width = 220; // 直接设置宽度
entity.billboard.height = 50; // 直接设置高度
allEntities.push(entity);
// 创建名字标签实体
const labelEntit = viewer.entities.add({
position: cartesian,
label: {
text: item.name,
font: 'bold 14px sans-serif',
fillColor: Cesium.Color.WHITE,
outlineColor: Cesium.Color.BLACK,
outlineWidth: 2,
style: Cesium.LabelStyle.FILL_AND_OUTLINE,
pixelOffset: new Cesium.Cartesian2(0, -36), // 位置在标签框上方
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
heightReference: Cesium.HeightReference.RELATIVE_TO_GROUND,
scaleByDistance: new Cesium.NearFarScalar(1000, 1, 5000, 0.5),
distanceDisplayCondition: new Cesium.DistanceDisplayCondition(0, 10000)
},
properties: {
type: item.type
}
});
allEntities.push(labelEntit);
iconEntities.value.push({
labelExtity: labelEntit,
entity
});
}
return { pins, allEntities };
}
...@@ -7,66 +7,37 @@ let personEntity: any; ...@@ -7,66 +7,37 @@ let personEntity: any;
const iconEntities = ref<any[]>([]); const iconEntities = ref<any[]>([]);
const pins: any = []; const pins: any = [];
// 点位图标 // 点位图标
export async function iconPoint(viewer: any, data: any, type: any) { export async function iconPoint(viewer: any, pins: any) {
console.log('--1--', data); // // 批量移除实体
iconEntities.value.forEach(item => {
const typeIcons = { viewer.entities.remove(item.labelExtity);
person_: new URL('@/assets/blueperson.png', import.meta.url).href, viewer.entities.remove(item.entity);
car_: new URL('@/assets/icon15.png', import.meta.url).href,
slope_: new URL('@/assets/icon17.png', import.meta.url).href,
default: new URL('@/assets/blueperson.png', import.meta.url).href
};
// 清除所有以当前type前缀开头的实体,确保每次调用都是全新的
const entitiesToRemove: any[] = [];
viewer.entities.values.forEach((entity: any) => {
if (typeof entity.id === 'string' && entity.id.startsWith(type)) {
entitiesToRemove.push(entity);
}
}); });
// 批量移除实体 for (const item of pins) {
entitiesToRemove.forEach(entity => viewer.entities.remove(entity)); if (item.entity) {
viewer.entities.remove(item.entity);
}
const cartographic = Cesium.Cartographic.fromDegrees(item.position.lon, item.position.lat);
for (let i = 0; i < data.value.length; i++) {
const cartographic = Cesium.Cartographic.fromDegrees(data.value[i].lon, data.value[i].lat);
const height = await getElevationFromRays(cartographic, viewer); const height = await getElevationFromRays(cartographic, viewer);
// 将高度增加一些,确保标签和图标在地形上方
const adjustedHeight = height + 1;
const cartesian = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, adjustedHeight);
const iconPath = typeIcons[type as keyof typeof typeIcons] || typeIcons.default;
// 创建实体ID使用传入的type前缀 const cartesian = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, height);
const entityId = `${type}${i}`;
// 检查是否已存在相同ID的实体,如果存在则移除 item.entity = viewer.entities.add({
const existingEntity = viewer.entities.getById(entityId);
if (existingEntity) {
viewer.entities.remove(existingEntity);
}
// 创建人员/车辆图标实体
personEntity = viewer.entities.add({
id: entityId, // 使用传入的type前缀确保唯一性
position: cartesian, position: cartesian,
billboard: { billboard: {
image: iconPath, image: item.image,
verticalOrigin: Cesium.VerticalOrigin.BOTTOM, verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
horizontalOrigin: Cesium.HorizontalOrigin.CENTER, horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
scale: 0.5, scale: 0.5,
heightReference: Cesium.HeightReference.RELATIVE_TO_GROUND heightReference: Cesium.HeightReference.RELATIVE_TO_GROUND
}, },
properties: { properties: {
type: data.value[i].type type: item.type
},
// 存储人员数据
personData: {
index: i,
info: data.value[i]
} }
}); });
// 创建标签框背景实体
const entity = viewer.entities.add({ const entity = viewer.entities.add({
position: cartesian, position: cartesian,
billboard: { billboard: {
...@@ -76,9 +47,6 @@ export async function iconPoint(viewer: any, data: any, type: any) { ...@@ -76,9 +47,6 @@ export async function iconPoint(viewer: any, data: any, type: any) {
scale: 0.5, scale: 0.5,
pixelOffset: new Cesium.Cartesian2(0, -30), // 位置在图标上方 pixelOffset: new Cesium.Cartesian2(0, -30), // 位置在图标上方
heightReference: Cesium.HeightReference.RELATIVE_TO_GROUND heightReference: Cesium.HeightReference.RELATIVE_TO_GROUND
},
properties: {
type: data.value[i].type
} }
}); });
entity.billboard.width = 220; // 直接设置宽度 entity.billboard.width = 220; // 直接设置宽度
...@@ -88,7 +56,7 @@ export async function iconPoint(viewer: any, data: any, type: any) { ...@@ -88,7 +56,7 @@ export async function iconPoint(viewer: any, data: any, type: any) {
const labelEntit = viewer.entities.add({ const labelEntit = viewer.entities.add({
position: cartesian, position: cartesian,
label: { label: {
text: data.value[i].carNumber || data.value[i].realName, text: item.name,
font: 'bold 14px sans-serif', font: 'bold 14px sans-serif',
fillColor: Cesium.Color.WHITE, fillColor: Cesium.Color.WHITE,
outlineColor: Cesium.Color.BLACK, outlineColor: Cesium.Color.BLACK,
...@@ -100,23 +68,17 @@ export async function iconPoint(viewer: any, data: any, type: any) { ...@@ -100,23 +68,17 @@ export async function iconPoint(viewer: any, data: any, type: any) {
heightReference: Cesium.HeightReference.RELATIVE_TO_GROUND, heightReference: Cesium.HeightReference.RELATIVE_TO_GROUND,
scaleByDistance: new Cesium.NearFarScalar(1000, 1, 5000, 0.5), scaleByDistance: new Cesium.NearFarScalar(1000, 1, 5000, 0.5),
distanceDisplayCondition: new Cesium.DistanceDisplayCondition(0, 10000) distanceDisplayCondition: new Cesium.DistanceDisplayCondition(0, 10000)
},
properties: {
type: data.value[i].type
} }
}); });
iconEntities.value.push(personEntity, entity, labelEntit); // 存储标签实体到pins数组中,以便主组件控制显示隐藏
item.labelEntity = labelEntit;
item.backgroundEntity = entity;
pins.push({ iconEntities.value.push({
entity: personEntity, labelExtity: labelEntit,
cardId: data.value[i].cardId, entity
type: personEntity.id,
position: cartesian,
label: null,
data: data.value[i]
}); });
} }
return pins; return pins;
} }
src/assets/blueperson.png

1.69 KB | W: | H:

src/assets/blueperson.png

1.76 KB | W: | H:

src/assets/blueperson.png
src/assets/blueperson.png
src/assets/blueperson.png
src/assets/blueperson.png
  • 2-up
  • Swipe
  • Onion skin
src/assets/jinrun/bg-left.png

219 KB | W: | H:

src/assets/jinrun/bg-left.png

233 KB | W: | H:

src/assets/jinrun/bg-left.png
src/assets/jinrun/bg-left.png
src/assets/jinrun/bg-left.png
src/assets/jinrun/bg-left.png
  • 2-up
  • Swipe
  • Onion skin
src/assets/jinrun/bg-right.png

219 KB | W: | H:

src/assets/jinrun/bg-right.png

233 KB | W: | H:

src/assets/jinrun/bg-right.png
src/assets/jinrun/bg-right.png
src/assets/jinrun/bg-right.png
src/assets/jinrun/bg-right.png
  • 2-up
  • Swipe
  • Onion skin
src/assets/jinrun/module-bg.png

51.5 KB | W: | H:

src/assets/jinrun/module-bg.png

51.5 KB | W: | H:

src/assets/jinrun/module-bg.png
src/assets/jinrun/module-bg.png
src/assets/jinrun/module-bg.png
src/assets/jinrun/module-bg.png
  • 2-up
  • Swipe
  • Onion skin
src/assets/jinrun/top.png

194 KB | W: | H:

src/assets/jinrun/top.png

199 KB | W: | H:

src/assets/jinrun/top.png
src/assets/jinrun/top.png
src/assets/jinrun/top.png
src/assets/jinrun/top.png
  • 2-up
  • Swipe
  • Onion skin
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
></canvas> ></canvas>
<div class="legend-container"> <div class="legend-container">
<div v-for="(item, index) in chartData" :key="index" class="legend-item"> <div v-for="(item, index) in chartData" :key="index" class="legend-item">
<div class="color-block" :style="{ backgroundColor: item.color || 'fff' }"></div> <div class="color-block" :style="{ backgroundColor: item.color }"></div>
<div class="legend-text"> <div class="legend-text">
<span class="legend-name">{{ item.name }}</span> <span class="legend-name">{{ item.name }}</span>
<span class="legend-value" :style="`color: ${item.color}`">{{ item.value }}</span> <span class="legend-value" :style="`color: ${item.color}`">{{ item.value }}</span>
...@@ -23,11 +23,7 @@ ...@@ -23,11 +23,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, onMounted, onBeforeUnmount, nextTick, reactive } from 'vue' import { ref, onMounted, watch } from 'vue';
import { getCarLogList } from '@/api/index-dp';
import { useMessage } from 'naive-ui';
const message = useMessage();
// 1. 定义 TS 类型接口 // 1. 定义 TS 类型接口
interface ChartDataItem { interface ChartDataItem {
...@@ -42,8 +38,13 @@ interface RingLayer { ...@@ -42,8 +38,13 @@ interface RingLayer {
} }
// 2. 核心配置与数据(5个类别) // 2. 核心配置与数据(5个类别)
// 使用 ref 创建响应式数据 const chartData: ChartDataItem[] = [
const chartData = ref<ChartDataItem[]>([]); { name: '疲劳驾驶', value: 10, color: '#409EFF' },
{ name: '违规打电话', value: 15, color: '#52C41A' },
{ name: '违规抽烟', value: 0, color: '#FAAD14' },
{ name: '左顾右盼', value: 2, color: '#FA8C16' },
{ name: '人脸丢失', value: 0, color: '#F5222D' },
];
// 调整环形图层尺寸以适应新的 canvas 尺寸,增大环间距离 // 调整环形图层尺寸以适应新的 canvas 尺寸,增大环间距离
const ringLayers: RingLayer[] = [ const ringLayers: RingLayer[] = [
...@@ -93,7 +94,7 @@ const drawChart = () => { ...@@ -93,7 +94,7 @@ const drawChart = () => {
// 步骤2:按比例绘制数值扇区 // 步骤2:按比例绘制数值扇区
const drawSectors = () => { const drawSectors = () => {
const validData = chartData.value.filter((item) => item.value > 0); const validData = chartData.filter((item) => item.value > 0);
const total = validData.reduce((sum, item) => sum + item.value, 0); const total = validData.reduce((sum, item) => sum + item.value, 0);
if (total === 0) { if (total === 0) {
console.warn('No valid data to draw'); console.warn('No valid data to draw');
...@@ -105,7 +106,7 @@ const drawChart = () => { ...@@ -105,7 +106,7 @@ const drawChart = () => {
// 先绘制背景 // 先绘制背景
drawBackground(); drawBackground();
chartData.value.forEach((item, index) => { chartData.forEach((item, index) => {
if (item.value <= 0) return; if (item.value <= 0) return;
const layer = ringLayers[index]; const layer = ringLayers[index];
if (!layer) return; if (!layer) return;
...@@ -136,36 +137,22 @@ const drawChart = () => { ...@@ -136,36 +137,22 @@ const drawChart = () => {
// 5. 挂载后初始化图表(DOM 渲染完成后执行) // 5. 挂载后初始化图表(DOM 渲染完成后执行)
onMounted(() => { onMounted(() => {
getCarLogList().then((response) => { console.log('Component mounted, attempting to draw chart');
if (response.data.code == 200) { // 使用 nextTick 确保 DOM 已完全渲染
// 使用 ref 的 value 属性更新数据,确保是响应式的 setTimeout(() => {
chartData.value = response.data.data.map((item: any) => ({ drawChart();
name: item.name, }, 0);
value: item.count * 1,
color: item.color
}));
console.log('*****************************', chartData.value);
console.log('Component mounted, attempting to draw chart');
// 使用 nextTick 确保 DOM 已完全渲染
nextTick(() => {
drawChart();
});
} else {
message.error(response.data.msg);
}
}).catch((error) => {
console.error('获取数据失败:', error);
message.error('获取数据失败');
});
}); });
// // 可选:监听数据变化重新绘制(如需动态更新数据可启用) // 可选:监听数据变化重新绘制(如需动态更新数据可启用)
// import { watch } from 'vue'; watch([() => chartData], () => {
// watch(chartData, () => { drawChart();
// drawChart(); }, { deep: true });
// }, { deep: true });
// 导出绘制函数以便外部调用
defineExpose({
drawChart
});
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
...@@ -173,7 +160,7 @@ onMounted(() => { ...@@ -173,7 +160,7 @@ onMounted(() => {
width: 100%; width: 100%;
overflow: auto; overflow: auto;
background-image: url("@/assets/jinrun/module-bg.png"); background-image: url("@/assets/jinrun/module-bg.png");
background-size: cover; background-size: cover;
background-repeat: no-repeat; background-repeat: no-repeat;
} }
...@@ -202,10 +189,10 @@ onMounted(() => { ...@@ -202,10 +189,10 @@ onMounted(() => {
align-items: center; align-items: center;
margin-bottom: 15px; margin-bottom: 15px;
width: 2.3rem; width: 2.3rem;
height: 0.28rem; height: 0.28rem;
background: #144f8025; background: #144f8025;
border-radius: 0.14rem; border-radius: 0.14rem;
padding-left: 0.3rem; padding-left: 0.3rem;
} }
.color-block { .color-block {
...@@ -216,21 +203,25 @@ onMounted(() => { ...@@ -216,21 +203,25 @@ onMounted(() => {
} }
.legend-text { .legend-text {
display: flex; display: flex;
gap: 0.1rem; gap: 0.1rem;
justify-content: space-between; justify-content: space-between;
width: 1.3rem; width: 1.3rem;
padding-left: .12rem; padding-left: .12rem;
} }
// .legend-text:first-child{
// display: inline-block;
// text-align: left;
// }
.legend-name { .legend-name {
font-size: .16rem; font-size: 12px;
color: #fff; color: #fff;
margin-bottom: 2px; margin-bottom: 2px;
} }
.legend-value { .legend-value {
font-size: .16rem; font-size: 12px;
color: #666; color: #666;
} }
......
...@@ -276,8 +276,8 @@ const local: App.I18n.Schema = { ...@@ -276,8 +276,8 @@ const local: App.I18n.Schema = {
orientation_monitor_rainfall: '降雨量历史', orientation_monitor_rainfall: '降雨量历史',
orientation_video: '摄像头管理', orientation_video: '摄像头管理',
orientation: '全方位监测监控系统', orientation: '全方位监测监控系统',
monitoring_data_detection: '排土场-表面位移', monitoring_data_detection: '边坡-表面位移',
monitoring_data_rainfall: '排土场-降雨量', monitoring_data_rainfall: '边坡-降雨量',
monitoring_home: '主页', monitoring_home: '主页',
monitoring_monitor_entering: '监测值录入', monitoring_monitor_entering: '监测值录入',
monitoring_monitor_manage: '监测点管理', monitoring_monitor_manage: '监测点管理',
......
...@@ -185,4 +185,17 @@ export const modelsRules: FormRules = { ...@@ -185,4 +185,17 @@ export const modelsRules: FormRules = {
trigger: 'blur' trigger: 'blur'
} }
] ]
}; };
\ No newline at end of file
// 登录
export const loginRules: FormRules = {
username: [
{ type: 'string', required: true, message: '请输入用户名', trigger: 'blur' }
],
password: [
{ type: 'string', required: true, message: '请输入密码', trigger: 'blur' }
],
yzmcode: [
{ type: 'string', required: true, message: '请输入验证码', trigger: 'blur' }
]
}
\ No newline at end of file
...@@ -15,7 +15,6 @@ declare module 'vue' { ...@@ -15,7 +15,6 @@ declare module 'vue' {
AppProvider: typeof import('./../components/common/app-provider.vue')['default'] AppProvider: typeof import('./../components/common/app-provider.vue')['default']
BetterScroll: typeof import('./../components/custom/better-scroll.vue')['default'] BetterScroll: typeof import('./../components/custom/better-scroll.vue')['default']
ButtonIcon: typeof import('./../components/custom/button-icon.vue')['default'] ButtonIcon: typeof import('./../components/custom/button-icon.vue')['default']
copy: typeof import('./../components/MineMonitor/RightTodayAlarm copy.vue')['default']
CountTo: typeof import('./../components/custom/count-to.vue')['default'] CountTo: typeof import('./../components/custom/count-to.vue')['default']
DarkModeContainer: typeof import('./../components/common/dark-mode-container.vue')['default'] DarkModeContainer: typeof import('./../components/common/dark-mode-container.vue')['default']
ExceptionBase: typeof import('./../components/common/exception-base.vue')['default'] ExceptionBase: typeof import('./../components/common/exception-base.vue')['default']
...@@ -126,7 +125,6 @@ declare global { ...@@ -126,7 +125,6 @@ declare global {
const AppProvider: typeof import('./../components/common/app-provider.vue')['default'] const AppProvider: typeof import('./../components/common/app-provider.vue')['default']
const BetterScroll: typeof import('./../components/custom/better-scroll.vue')['default'] const BetterScroll: typeof import('./../components/custom/better-scroll.vue')['default']
const ButtonIcon: typeof import('./../components/custom/button-icon.vue')['default'] const ButtonIcon: typeof import('./../components/custom/button-icon.vue')['default']
const copy: typeof import('./../components/MineMonitor/RightTodayAlarm copy.vue')['default']
const CountTo: typeof import('./../components/custom/count-to.vue')['default'] const CountTo: typeof import('./../components/custom/count-to.vue')['default']
const DarkModeContainer: typeof import('./../components/common/dark-mode-container.vue')['default'] const DarkModeContainer: typeof import('./../components/common/dark-mode-container.vue')['default']
const ExceptionBase: typeof import('./../components/common/exception-base.vue')['default'] const ExceptionBase: typeof import('./../components/common/exception-base.vue')['default']
......
import { ref } from "vue";
let webRtcServrce = ref();
export function webVideo(rtsp: any) {
console.log('111',rtsp);
webRtcServrce.value = new WebRtcStreamer('video', location.protocol + '//' + "192.168.2.53:8000")
webRtcServrce.value.connect('rtsp://admin:Gemho120611@192.168.0.17:554/h264/ch1/main/av_stream');
};
<script setup lang="ts"> <script setup lang="ts">
import { onMounted, ref, watch } from 'vue'; import { nextTick, onBeforeMount, onMounted, onUnmounted, ref, watch } from 'vue';
import '../../../../Cesium/Widgets/widgets.css'; import '../../../../Cesium/Widgets/widgets.css';
import { useMessage } from 'naive-ui'; import { useMessage } from 'naive-ui';
import { getFenceListsApi } from '@/api'; import {
getCameraIdApi,
getCarPointAllCarApi,
getCemeraPointApi,
getFenceListsApi,
getHomeCarApi,
getMonitorIdApi,
getMonitorPointApi,
getPointAllPersonApi,
getPointListApi
} from '@/api';
import { create3D } from '@/api/utils/cesium'; import { create3D } from '@/api/utils/cesium';
import { getElevationFromRay, getElevationFromRays } from '@/api/utils/cesiumUtil'; import { getElevationFromRay, getElevationFromRays } from '@/api/utils/cesiumUtil';
import { cesiumToLongitudeAndLatitude } from '@/api/utils/coordinateUtil'; import { cesiumToLongitudeAndLatitude } from '@/api/utils/coordinateUtil';
import { getModel } from '@/api/utils/cesiumModel'; import { getModel } from '@/api/utils/cesiumModel';
import { iconPoint } from '@/api/utils/home/cesiumPositions';
import { carSpeed } from '@/api/utils/carSpeed';
import fullScreen from '@/utils/full'; import fullScreen from '@/utils/full';
import { webVideo } from '@/utils/ai';
import bluePersonIcon from '@/assets/blueperson.png'; import bluePersonIcon from '@/assets/blueperson.png';
import arrowLeftImg from '@/assets/jinrun/arrow-left.png';
import arrowRightImg from '@/assets/jinrun/arrow-right.png';
import redCarIcon from '@/assets/icon15Red.png';
import redVideoIcon from '@/assets/icon16Red.png';
import redBianIcon from '@/assets/icon17Red.png';
import blueCarIcon from '@/assets/icon15.png';
import blueVideoIcon from '@/assets/icon16.png';
import blueBianIcon from '@/assets/icon17.png';
import redPersonIcon from '../../../assets/redperson.png';
import MultiSelect from './appselect.vue'; import MultiSelect from './appselect.vue';
let viewer: any = null; let viewer: any = null;
...@@ -16,12 +38,17 @@ const message = useMessage(); ...@@ -16,12 +38,17 @@ const message = useMessage();
let personEntity: any; let personEntity: any;
const pins: any = []; const pins: any = [];
const full = ref(false); const full = ref(false);
let entityId: any;
let link: any;
let speed = 0;
let text = '';
const personList = ref([]);
const modelData = ref([ const modelData = ref([
[121.70966961471791, 36.86008449826527], [122.04736846370741, 37.48958083145254],
[121.70852773459532, 36.85709047622009], [122.04760069379522, 37.489226301608184],
[121.71154596109507, 36.8570398369999], [122.04823299200363, 37.489451482540346],
[121.7121957019953, 36.860359083384175], [122.04802271634016, 37.48983410372907],
[121.70966961471791, 36.86008449826527] [122.04748237248322, 37.49016152294277]
]); ]);
const options = [ const options = [
...@@ -31,11 +58,11 @@ const options = [ ...@@ -31,11 +58,11 @@ const options = [
}, },
{ {
label: '在线监测设备', label: '在线监测设备',
value: '2' value: '3'
}, },
{ {
label: '视频监控', label: '视频监控',
value: '3' value: '2'
}, },
{ {
label: '人员定位', label: '人员定位',
...@@ -51,95 +78,8 @@ const options = [ ...@@ -51,95 +78,8 @@ const options = [
} }
]; ];
const value = ref(options.map(opt => opt.value)); const value = ref(options.map(opt => opt.value));
// 监听选中值的变化
watch(
value,
(newVal, oldVal) => {
// 防止无限递归
if (JSON.stringify(newVal) === JSON.stringify(oldVal)) return;
// 获取除全选外的所有选项值
const otherValues = options.slice(1).map(opt => opt.value);
// 检查是否选中了所有其他选项
const allOtherSelected = otherValues.every(val => newVal.includes(val));
// 检查是否点击了全选
const allSelectedNow = newVal.includes('1');
const allSelectedBefore = oldVal.includes('1');
// 点击了全选选项
if (allSelectedNow && !allSelectedBefore) {
value.value = options.map(opt => opt.value);
return;
}
// 取消了全选选项
if (!allSelectedNow && allSelectedBefore) {
// 检查是否所有其他选项都被选中
const allOtherOptionsSelected = otherValues.every(val => newVal.includes(val));
if (allOtherOptionsSelected) {
// 如果所有其他选项都被选中,取消所有选中状态
value.value = [];
} else {
// 如果不是所有其他选项都被选中,只取消全选选项
value.value = newVal.filter(val => val !== '1');
}
return;
}
const someOptionUnselected = oldVal.length > newVal.length;
if (someOptionUnselected && allSelectedNow) {
// 如果取消了某个选项且当前处于全选状态,取消全选,但保留其他选项
value.value = newVal.filter(val => val !== '1');
}
// 选中了所有其他选项,自动选中全选 const data = ref([]);
if (allOtherSelected && !allSelectedNow) {
value.value = options.map(opt => opt.value);
}
// 如果取消了所有选项,清空value
if (newVal.length === 0) {
value.value = [];
}
},
{ deep: true }
);
const data = ref([
{
type: 1,
name: '仓房摄像头2',
x: 121.71061401132522,
y: 36.85887225892583
},
{
type: 2,
name: '边坡表面位移1',
x: 121.71008898290809,
y: 36.858159326215
},
{
type: 3,
name: '车辆1',
x: 121.71068916419333,
y: 36.8580421871238
},
{
type: 4,
name: '人工1',
x: 121.71115918429389,
y: 36.858735234993766
},
{
type: 5,
name: '人工2',
x: 121.71068034080756,
y: 36.85840370795711
}
]);
// let datasouce = ref<any>()
const position = ref([]);
const heightData = ref([]);
const datasouce = ref(); const datasouce = ref();
const fence = ref<any>(); const fence = ref<any>();
const personShow = ref(false); const personShow = ref(false);
...@@ -154,9 +94,56 @@ const fenceData = ref({ ...@@ -154,9 +94,56 @@ const fenceData = ref({
imagePath: '', imagePath: '',
imageColor: '' imageColor: ''
}); });
const labelData = ref<any>();
const formData = ref([]); const formData = ref([]);
// zhaojunbao 开始
// REM自适应配置
const active = ref(false);
const REM_CONFIG = {
// 设计稿宽度
designWidth: 1920,
designHeight: 1080,
// 基准值:1rem = 100px
baseSize: 100
};
// 跳转首页
const navTo = () => {
window.location.href = '/home';
};
/**
* 设置REM单位
* 根据窗口宽度动态计算根元素font-size
*/
const setRemUnit = () => {
const { designWidth, designHeight, baseSize } = REM_CONFIG;
// 获取当前窗口尺寸
const windowWidth = window.innerWidth;
const windowHeight = window.innerHeight;
// 计算宽高缩放比例
const scaleX = windowWidth / designWidth;
const scaleY = windowHeight / designHeight;
// 取较小的缩放比例以适应屏幕,确保内容不会被裁剪
const scale = Math.min(scaleX, scaleY);
// 设置根元素font-size,确保最小为50px(可选)
const fontSize = Math.max(baseSize * scale, 50);
document.documentElement.style.fontSize = `${fontSize}px`;
};
// 控制左右模块显示状态的响应式变量
const isLeftModulesVisible = ref(true);
const isRightModulesVisible = ref(true);
const toggleBothModules = () => {
isLeftModulesVisible.value = !isLeftModulesVisible.value;
isRightModulesVisible.value = !isRightModulesVisible.value;
};
// zhaojunbao 结束
// 模型 // 模型
function add3dtiles() { function add3dtiles() {
const CesiumConfig = { const CesiumConfig = {
...@@ -191,7 +178,57 @@ function add3dtiles() { ...@@ -191,7 +178,57 @@ function add3dtiles() {
}); });
} }
// 监听 // 监听选中值的变化
watch(
value,
(newVal, oldVal) => {
// 防止无限递归
if (JSON.stringify(newVal) === JSON.stringify(oldVal)) return;
// 获取除全选外的所有选项值
const otherValues = options.slice(1).map(opt => opt.value);
// 检查是否选中了所有其他选项
const allOtherSelected = otherValues.every(val => newVal.includes(val));
// 检查是否点击了全选
const allSelectedNow = newVal.includes('1');
const allSelectedBefore = oldVal.includes('1');
// 点击了全选选项
if (allSelectedNow && !allSelectedBefore) {
value.value = options.map(opt => opt.value);
return;
}
// 取消了全选选项
if (!allSelectedNow && allSelectedBefore) {
// 检查是否所有其他选项都被选中
const allOtherOptionsSelected = otherValues.every(val => newVal.includes(val));
if (allOtherOptionsSelected) {
// 如果所有其他选项都被选中,取消所有选中状态
value.value = [];
} else {
// 如果不是所有其他选项都被选中,只取消全选选项
value.value = newVal.filter(val => val !== '1');
}
return;
}
const someOptionUnselected = oldVal.length > newVal.length;
if (someOptionUnselected && allSelectedNow) {
// 如果取消了某个选项且当前处于全选状态,取消全选,但保留其他选项
value.value = newVal.filter(val => val !== '1');
}
// 选中了所有其他选项,自动选中全选
if (allOtherSelected && !allSelectedNow) {
value.value = options.map(opt => opt.value);
}
// 如果取消了所有选项,清空value
if (newVal.length === 0) {
value.value = [];
}
},
{ deep: true }
);
// 监听选择框的变化 // 监听选择框的变化
watch( watch(
value, value,
...@@ -429,398 +466,567 @@ function electronic(position: any, heightData: any, rangeType: any) { ...@@ -429,398 +466,567 @@ function electronic(position: any, heightData: any, rangeType: any) {
loadWall(); loadWall();
} }
// 点位图标 // 点击弹框隐藏
async function iconPoint() { function videosShow() {
const typeIcons = { if (videoShow.value == true) {
1: new URL('@/assets/icon16.png', import.meta.url).href, videoShow.value = false;
2: new URL('@/assets/icon17.png', import.meta.url).href, iconShow();
3: new URL('@/assets/icon15.png', import.meta.url).href, }
4: new URL('@/assets/redperson.png', import.meta.url).href, }
5: new URL('@/assets/blueperson.png', import.meta.url).href function equipmentsShow() {
}; if (equipmentShow.value == true) {
for (let i = 0; i < data.value.length; i++) { equipmentShow.value = false;
const cartographic = Cesium.Cartographic.fromDegrees(data.value[i].x, data.value[i].y); iconShow();
const height = await getElevationFromRays(cartographic, viewer); }
// 将高度增加一些,确保标签和图标在地形上方 }
const adjustedHeight = height + 1; function carsShow() {
const cartesian = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, adjustedHeight); if (carShow.value == true) {
const iconPath = typeIcons[data.value[i].type as keyof typeof typeIcons] || bluePersonIcon; carShow.value = false;
// 创建人员图标实体 iconShow();
personEntity = viewer.entities.add({ }
id: `person_${i}`, // 为人员图标实体设置特定前缀的ID }
position: cartesian, function personsShow() {
billboard: { if (personShow.value == true) {
image: iconPath, personShow.value = false;
verticalOrigin: Cesium.VerticalOrigin.BOTTOM, iconShow();
horizontalOrigin: Cesium.HorizontalOrigin.CENTER, }
scale: 0.5, }
heightReference: Cesium.HeightReference.RELATIVE_TO_GROUND
},
properties: {
type: data.value[i].type
}
});
// 创建标签框背景实体 function iconShow() {
const entity = viewer.entities.add({ for (const item of pins) {
position: cartesian, if (item.type == 1) {
billboard: { item.image = bluePersonIcon;
image: new URL('../../../assets/titlePerson.png', import.meta.url).href, } else if (item.type == 2) {
verticalOrigin: Cesium.VerticalOrigin.BOTTOM, item.image = blueCarIcon;
horizontalOrigin: Cesium.HorizontalOrigin.CENTER, } else if (item.type == 3) {
scale: 0.5, item.image = blueBianIcon;
pixelOffset: new Cesium.Cartesian2(0, -30), // 位置在图标上方 } else {
heightReference: Cesium.HeightReference.RELATIVE_TO_GROUND item.image = blueVideoIcon;
}, }
properties: { }
type: data.value[i].type iconPoint(viewer, pins);
} }
});
entity.billboard.width = 220; // 直接设置宽度
entity.billboard.height = 50; // 直接设置高度
// 创建名字标签实体
const labelEntit = viewer.entities.add({
position: cartesian,
label: {
text: data.value[i].name,
font: 'bold 14px sans-serif',
fillColor: Cesium.Color.WHITE,
outlineColor: Cesium.Color.BLACK,
outlineWidth: 2,
style: Cesium.LabelStyle.FILL_AND_OUTLINE,
pixelOffset: new Cesium.Cartesian2(0, -36), // 位置在标签框上方
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
heightReference: Cesium.HeightReference.RELATIVE_TO_GROUND,
scaleByDistance: new Cesium.NearFarScalar(1000, 1, 5000, 0.5),
distanceDisplayCondition: new Cesium.DistanceDisplayCondition(0, 10000)
},
properties: {
type: data.value[i].type
}
});
iconEntities.value.push(personEntity, entity, labelEntit); // 设置员工类型
function getPersonTypeName(type: number): string {
switch (type) {
case 1:
return '员工';
case 2:
return '访客';
default:
return '没有该类型';
}
}
pins.push({ async function setTimePerson() {
entity: personEntity, const res = await getPointAllPersonApi();
position: cartesian, for (let item of pins) {
label: null, const pin = res.data.data.find((personData: any) => personData.cardId == item.id);
type: data.value[i].type if (pin) {
// text: ` 在线监测设备信息 \n 设备名称: ${} \n 设备状态:${} \n 设备类型:${} \n 监测值${} 监测时间: ${} \n 数据状态: ${}`\ item = pin;
}); }
}
const carRes = await getCarPointAllCarApi();
for (let item of pins) {
const pin = carRes.data.data.find((carData: any) => carData.carNumber == item.id);
if (pin) {
item = pin;
}
} }
iconPoint(viewer, pins);
} }
setInterval(setTimePerson, 10 * 1000);
onMounted(() => { onMounted(async () => {
add3dtiles(); add3dtiles();
setTimeout(async () => {
setTimeout(() => {
// electronic();
fenceListGet(); fenceListGet();
iconPoint();
const res = await getPointAllPersonApi();
const personData = res.data.data;
personData.map(item => {
pins.push({
id: item.cardId,
name: item.realName,
type: 1,
image: bluePersonIcon,
position: {
lon: item.lon,
lat: item.lat
},
data: item,
entity: null
});
});
// 获取并显示车辆数据,使用不同的前缀
const resCar = await getCarPointAllCarApi();
const carData = resCar.data.data;
carData.map(item => {
pins.push({
id: item.carNumber,
name: item.carNumber,
type: 2,
image: blueCarIcon,
position: {
lon: item.lon,
lat: item.lat
},
data: item,
entity: null
});
});
// 获取在线监测
const resPoint = await getMonitorPointApi();
const pointData = resPoint.data.data;
pointData.map(item => {
pins.push({
id: item.id,
type: 3,
name: item.equipname,
image: blueBianIcon,
position: {
lon: item.longitude,
lat: item.latitude
},
data: item,
entity: null,
label: null
});
});
// 获取视频监控信息
const resVideo = await getCemeraPointApi();
const videoData = resVideo.data.data;
videoData.map(item => {
pins.push({
id: item.id,
name: item.cameraName,
type: 4,
image: blueVideoIcon,
position: {
lon: item.lon,
lat: item.lat
},
data: item,
entity: null
});
});
iconPoint(viewer, pins).then(result => {
console.log(result);
});
}, 2000); }, 2000);
// setTimePerson();
setRemUnit();
// 监听窗口大小变化
window.addEventListener('resize', setRemUnit);
// zhaojunbao 结束
const handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas); const handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
// 鼠标点击事件
handler.setInputAction(function (click: any) { handler.setInputAction(async function (click: any) {
const pickedObject = viewer.scene.pick(click.position); const pickedObject = viewer.scene.pick(click.position);
if (!pickedObject.collection) {
videoShow.value = false; for (const item of pins) {
equipmentShow.value = false; if (item.type == 1) {
carShow.value = false; item.image = bluePersonIcon;
personShow.value = false; } else if (item.type == 2) {
return; item.image = blueCarIcon;
} else if (item.type == 3) {
item.image = blueBianIcon;
} else {
item.image = blueVideoIcon;
}
} }
if (Cesium.defined(pickedObject) && pickedObject.id) {
const pin = pins.find(p => p.entity === pickedObject.id); if (Cesium.defined(pickedObject) && Cesium.defined(pickedObject.id)) {
const pin = pins.find(item => item.entity === pickedObject.id);
if (pin.type == 1) { if (pin.type == 1) {
videoShow.value = true; equipmentShow.value = false;
videoShow.value = false;
carShow.value = false;
personShow.value = true;
labelData.value = pin.data;
pin.image = redPersonIcon;
} else if (pin.type == 2) { } else if (pin.type == 2) {
equipmentShow.value = true; // 车
} else if (pin.type == 3) { equipmentShow.value = false;
videoShow.value = false;
personShow.value = false;
carShow.value = true; carShow.value = true;
const res = await getHomeCarApi(pin.id);
console.log(res);
if (res.data.code == 200) {
speed = res.data.data.point ? carSpeed(res.data.data) : 0;
labelData.value = res.data.data;
}
pin.image = redCarIcon;
} else if (pin.type == 3) {
// 监测设备
videoShow.value = false;
carShow.value = false;
personShow.value = false;
equipmentShow.value = true;
const res = await getMonitorIdApi(pin.id);
if (res.data.code == 200) {
if (res.data.data.devicetype == 3) {
text = '表面位移';
} else if (res.data.data.devicetype == 6) {
text = '降雨量';
}
labelData.value = res.data.data;
}
pin.image = redBianIcon;
} else { } else {
personShow.value = true; // 摄像头
equipmentShow.value = false;
videoShow.value = true;
carShow.value = false;
personShow.value = false;
videoShow.value = true;
const res = await getCameraIdApi(pin.id);
if (res.data.code == 200) {
labelData.value = res.data.data;
console.log(labelData.value);
const webRtcServrce = ref();
nextTick(() => {
webRtcServrce.value = new WebRtcStreamer('video', `${location.protocol}//` + `192.168.2.53:8000`);
webRtcServrce.value.connect(res.data.data.videoStream);
});
}
pin.image = redVideoIcon;
} }
// pinsModel(pin,viewer); iconPoint(viewer, pins);
} else { } else {
videoShow.value = false;
equipmentShow.value = false; equipmentShow.value = false;
videoShow.value = false;
carShow.value = false; carShow.value = false;
personShow.value = false; personShow.value = false;
iconPoint(viewer, pins);
} }
}, Cesium.ScreenSpaceEventType.LEFT_CLICK); }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
}); });
onUnmounted(() => {
// 清理Cesium资源
if (viewer) {
viewer.destroy();
viewer = null;
}
// 移除窗口大小变化监听
window.removeEventListener('resize', setRemUnit);
// 移除html元素style属性中的font-size
document.documentElement.style.fontSize = '';
});
</script> </script>
<template> <template>
<div class="cesium-container"> <div class="wrapper">
<div id="cesiumContainer"> <div class="top-toolbar">
<!-- 选择框 --> <div class="baojing">
<!-- 声光报警
<NSpace vertical style="width: 220px; height: 36px; position: fixed; z-index: 999; top: 80px; left: 70%"> <NSwitch v-model:value="active" />
<NSelect
v-model:value="value"
class="select"
multiple
:options="options"
default-value="all"
:max-tag-count="1"
popup-class="cesium-select-popup"
/>
</NSpace>
-->
<MultiSelect v-model="value" :options="options" style="position: fixed; z-index: 999; top: 80px; left: 70%" />
<!-- 人员信息弹框 -->
<div v-if="personShow == true" class="personMessage">
<div style="display: flex; justify-content: flex-start; align-items: center; margin-bottom: 10px">
<div style="width: 90%; margin: 0; font-size: 16px">
<span>人员信息</span>
<div class="person1"></div>
</div>
<button
id="close-info"
style="background: none; border: none; color: white; cursor: pointer; font-size: 18px; margin-left: 10px"
>
&times;
</button>
</div>
<div style="line-height: 1.8">
<p class="title1">
<strong class="title2">姓名:</strong>
赵薇
</p>
<p class="title1">
<strong class="title2">定位卡号:</strong>
ED001
</p>
<p class="title1">
<strong class="title2">人员类型:</strong>
员工/访客
</p>
<p class="title1">
<strong class="title2">电话:</strong>
1817456556
</p>
<p class="title1">
<strong class="title2">部门:</strong>
生产部
</p>
</div>
</div> </div>
<!-- 车辆信息 -->
<div v-if="carShow == true" class="carMessage"> <!-- <i class="split-line"></i> -->
<div style="display: flex; justify-content: flex-start; align-items: center; margin-bottom: 10px"> <div class="split-line"></div>
<div style="width: 90%; margin: 0; font-size: 16px"> <div class="houtaiguanli" @click="navTo">后台管理</div>
<span>车辆信息</span> </div>
<div class="person1"></div> <!-- cesium 容器 -->
<div class="cesium-container">
<div id="cesiumContainer">
<!-- 选择框 -->
<MultiSelect v-model="value" :options="options" style="position: fixed; z-index: 999; top: 100px; left: 63%" />
<!-- 人员信息弹框 -->
<div v-if="personShow == true" class="personMessage">
<div style="display: flex; justify-content: flex-start; align-items: center; margin-bottom: 10px">
<div style="width: 90%; margin: 0; font-size: 16px">
<span>人员信息</span>
<div class="person1"></div>
</div>
<button
id="close-info"
style="background: none; border: none; color: white; cursor: pointer; font-size: 18px; margin-left: 10px"
@click="personsShow()"
>
&times;
</button>
</div>
<div style="line-height: 1.8">
<p class="title1">
<strong class="title2">姓名:</strong>
{{ labelData.realName }}
</p>
<p class="title1">
<strong class="title2">定位卡号:</strong>
{{ labelData.cardId }}
</p>
<p class="title1">
<strong class="title2">人员类型:</strong>
{{ getPersonTypeName(labelData.personType) }}
</p>
<p class="title1">
<strong class="title2">电话:</strong>
{{ labelData.phone }}
</p>
<p class="title1">
<strong class="title2">部门:</strong>
{{ labelData.deptName }}
</p>
</div> </div>
<button
id="close-info"
style="background: none; border: none; color: white; cursor: pointer; font-size: 18px; margin-left: 10px"
>
&times;
</button>
</div> </div>
<div style="line-height: 1.8; display: flex; justify-content: space-between"> <!-- 车辆信息 -->
<div class="left"> <div v-if="carShow == true" class="carMessage">
<div class="left-top"> <div style="display: flex; justify-content: flex-start; align-items: center; margin-bottom: 10px">
<p class="title1"> <div style="width: 90%; margin: 0; font-size: 16px">
<strong class="title2">车牌号:</strong> <span>车辆信息</span>
鲁K:534435 <div class="person1"></div>
</p>
<p class="title1">
<strong class="title2">车队名称:</strong>
KC001
</p>
<p class="title1">
<strong class="title2">当前车速:</strong>
25km/h
</p>
<p class="title1">
<strong class="title2">车辆类型:</strong>
卡车
</p>
</div>
<div class="left-center"></div>
<div class="left-bottom">
<p class="title1">
<strong class="title2">司机姓名:</strong>
张喂
</p>
<p class="title1">
<strong class="title2">工作开始时间:</strong>
8:30
</p>
<p class="title1">
<strong class="title2">工作时长:</strong>
3H
</p>
<p class="title1">
<strong class="title2">终端设备编号:</strong>
ZD000001
</p>
</div> </div>
</div> <button
<div class="right"> id="close-info"
<!-- style="background: none; border: none; color: white; cursor: pointer; font-size: 18px; margin-left: 10px"
<video id="video" controls autoplay muted playsinline width="100%" height="100%" @click="carsShow()"
style="object-fit: fill; z-index: 1;"></video>
-->
<div
:style="
full
? {
border: '1px solid #ccc',
padding: '2px',
position: 'fixed',
top: 0,
left: 0,
width: '100vw',
height: '100px',
zIndex: '99'
}
: {
padding: '2px',
height: '250px !important',
border: ' 1px solid #ccc',
position: 'relative'
}
"
> >
<div style="position: absolute; bottom: 5px; right: 5px; width: 40px; height: 40px; cursor: pointer"> &times;
<icon-gridicons-fullscreen-exit </button>
v-if="full" </div>
color="#11e0ff" <div style="line-height: 1.8; display: flex; justify-content: space-between">
font-size="30" <div class="car-left">
@click="full = fullScreen(full)" <div class="left-top">
/> <p class="title1">
<icon-gridicons-fullscreen v-else font-size="30" color="#11e0ff" @click="full = fullScreen(full)" /> <strong class="title2">车牌号:</strong>
{{ labelData.carNumber || '暂无数据' }}
</p>
<p class="title1">
<strong class="title2">车队名称:</strong>
{{ labelData.teamName || '暂无数据' }}
</p>
<p class="title1">
<strong class="title2">当前车速:</strong>
{{ speed }} km/h
</p>
<p class="title1">
<strong class="title2">车辆类型:</strong>
{{ labelData.carType || '暂无数据' }}
</p>
</div>
<div class="left-center"></div>
<div class="left-bottom">
<p class="title1">
<strong class="title2">司机姓名:</strong>
{{ labelData.driverName || '暂无数据' }}
</p>
<p class="title1">
<strong class="title2">工作开始时间:</strong>
{{ labelData.workStartTime || '暂无数据' }}
</p>
<p class="title1">
<strong class="title2">工作时长:</strong>
{{ labelData.workTime || '暂无数据' }}
</p>
<p class="title1">
<strong class="title2">终端设备编号:</strong>
{{ labelData.terminalNumber || '暂无数据' }}
</p>
</div> </div>
<canvas id="canvas-4" style="width: 100%; height: 100%" width="800" height="600"></canvas> </div>
<div class="car-right">
<iframe
allowfullscreen="true"
allowtransparency="true"
allow="autoplay"
scrolling="no"
:src="link"
width="100%"
height="100%"
frameborder="0"
style="padding-right: 20px"
></iframe>
<!-- '${res.ipAddress}?lang=zh&devIdno=${res.cameraNo}&account=${res.username}&password=${res.password}&channel=1' -->
</div> </div>
</div> </div>
</div> </div>
</div> <!-- 在线检测设备信息 -->
<!-- 在线检测设备信息 --> <div v-if="equipmentShow == true" class="equipmentMessage">
<div v-if="equipmentShow == true" class="equipmentMessage"> <div style="display: flex; justify-content: flex-start; align-items: center; margin-bottom: 10px">
<div style="display: flex; justify-content: flex-start; align-items: center; margin-bottom: 10px"> <div style="width: 90%; margin: 0; font-size: 16px">
<div style="width: 90%; margin: 0; font-size: 16px"> <span>在线检测设备信息</span>
<span>在线检测设备信息</span> <div class="person1"></div>
<div class="person1"></div> </div>
<button
id="close-info"
style="background: none; border: none; color: white; cursor: pointer; font-size: 18px; margin-left: 10px"
@click="equipmentsShow()"
>
&times;
</button>
</div> </div>
<button <div style="line-height: 1.8">
id="close-info" <p class="title1">
style="background: none; border: none; color: white; cursor: pointer; font-size: 18px; margin-left: 10px" <strong class="title2">设备名称:</strong>
> {{ labelData.equipname }}
&times; </p>
</button> <p class="title1">
</div> <strong class="title2">设备状态:</strong>
<div style="line-height: 1.8"> {{ labelData.dataStatus === 0 ? '在线' : '离线' }}
<p class="title1"> </p>
<strong class="title2">设备名称:</strong> <p class="title1">
设备表面位移01 <strong class="title2">设备类型:</strong>
</p> {{ text }}
<p class="title1"> </p>
<strong class="title2">设备状态:</strong> <p class="title1">
在线/离线 <strong class="title2">监测值:</strong>
</p> {{ labelData.value }}
<p class="title1"> </p>
<strong class="title2">设备类型:</strong> <p class="title1">
表面位移/降雨量/环境监测 <strong class="title2">监测时间:</strong>
</p> {{ labelData.time }}
<p class="title1"> </p>
<strong class="title2">监测值:</strong> <p class="title1">
0.004mm <strong class="title2">数据状态:</strong>
</p> {{ labelData.onlineStatus === 0 ? '正常' : '蓝色报警' }}
<p class="title1"> </p>
<strong class="title2">监测时间:</strong>
2025-10 10:10:10
</p>
<p class="title1">
<strong class="title2">数据状态:</strong>
正常
</p>
</div>
</div>
<!-- 视频监控信息 -->
<div v-if="videoShow == true" class="videoMessage">
<div style="display: flex; justify-content: flex-start; align-items: center; margin-bottom: 10px">
<div style="width: 90%; margin: 0; font-size: 16px">
<span>视频监控信息</span>
<div class="person1"></div>
</div> </div>
<button
id="close-info"
style="background: none; border: none; color: white; cursor: pointer; font-size: 18px; margin-left: 10px"
>
&times;
</button>
</div> </div>
<div style="line-height: 1.8; display: flex; flex-direction: column; flex-wrap: nowrap"> <!-- 视频监控信息 -->
<div class="video-top"> <div v-if="videoShow == true" class="videoMessage">
<div class="title3"> <div style="display: flex; justify-content: flex-start; align-items: center; margin-bottom: 10px">
<strong class="title2">● 摄像头名称:</strong> <div style="width: 90%; margin: 0; font-size: 16px">
排土场入口 <span>视频监控信息</span>
</div> <div class="person1"></div>
<div class="title3">
<strong class="title4">● 区域名称:</strong>
排土场背部
</div>
<div class="title3">
<strong class="title4">● 设备状态:</strong>
在线/离线
</div> </div>
</div> <button
<div class="video-bottom"> id="close-info"
<div style="background: none; border: none; color: white; cursor: pointer; font-size: 18px; margin-left: 10px"
:style=" @click="videosShow()"
full
? {
border: '1px solid #ccc',
padding: '2px',
position: 'fixed',
top: 0,
left: 0,
width: '100vw',
height: '100px',
zIndex: '99'
}
: {
padding: '2px',
height: '250px !important',
border: ' 1px solid #ccc',
position: 'relative'
}
"
> >
<div style="position: absolute; bottom: 5px; right: 5px; width: 40px; height: 40px; cursor: pointer"> &times;
<icon-gridicons-fullscreen-exit </button>
v-if="full" </div>
color="#11e0ff" <div style="line-height: 1.8; display: flex; flex-direction: column; flex-wrap: nowrap">
font-size="30" <div class="video-top">
@click="full = fullScreen(full)" <div class="title3">
/> <strong class="title2">● 摄像头名称:</strong>
<icon-gridicons-fullscreen v-else font-size="30" color="#11e0ff" @click="full = fullScreen(full)" /> {{ labelData.areaName }}
</div> </div>
<canvas id="canvas-4" style="width: 100%; height: 100%" width="800" height="600"></canvas> <div class="title3">
<strong class="title4">● 区域名称:</strong>
{{ labelData.cameraName }}
</div>
<div class="title3">
<strong class="title4">● 设备状态:</strong>
{{ labelData.status === 0 ? '在线' : '离线' }}
</div>
</div>
<div class="video-bottom">
<video
id="video"
controls
autoplay
muted
playsinline
width="100%"
height="100%"
style="object-fit: fill; z-index: 1"
></video>
</div> </div>
</div> </div>
</div> </div>
<!-- </div> -->
</div>
</div>
</div>
<div class="top">
<div class="first-image">
<img src="@/assets/jinrun/top.png" alt="" srcset="" />
<div class="second-icon">
<img src="@/assets/jinrun/title.png" alt="" />
</div>
</div>
</div>
<div class="bottom"></div>
<div v-show="isLeftModulesVisible" class="left"></div>
<div v-show="isRightModulesVisible" class="right"></div>
<!-- 非cesium相关 开始 -->
<!-- 左侧收起按钮 -->
<div class="toggle-btn left-toggle" :class="{ collapsed: !isLeftModulesVisible }" @click="toggleBothModules">
<div class="btn-arrow1">
<div>
<img :src="isLeftModulesVisible ? arrowLeftImg : arrowRightImg" alt="" srcset="" />
<br />
<div class="arrow-font">
{{ isLeftModulesVisible ? '收起' : '展开' }}
</div>
</div> </div>
<!-- </div> -->
</div> </div>
</div> </div>
<!-- 右侧收起按钮 -->
<div class="toggle-btn right-toggle" :class="{ collapsed: !isRightModulesVisible }" @click="toggleBothModules">
<!-- <div class="btn-arrow1"><img src="@/assets/jinrun/arrow-right.png" alt="" srcset=""><br><br></div> -->
<div class="btn-arrow1">
<div>
<img :src="isLeftModulesVisible ? arrowRightImg : arrowLeftImg" alt="" srcset="" />
<br />
<div class="arrow-font">
{{ isLeftModulesVisible ? '收起' : '展开' }}
</div>
</div>
</div>
</div>
<!-- 左侧模块容器 -->
<Transition name="slide-left">
<div v-show="isLeftModulesVisible" class="left-modules">
<LeftDeviceStatus />
<LeftRainfallTrend />
<LeftOnlineMonitor />
</div>
</Transition>
<!-- 右侧模块容器 -->
<Transition name="slide-right">
<div v-show="isRightModulesVisible" class="right-modules">
<RightAiWarning />
<RightEnvMonitor />
<RightTodayAlarm />
</div>
</Transition>
<!-- 非cesium相关 结束 -->
</template> </template>
<style scoped> <style scoped>
html,
body {
width: 100%;
height: 100%;
overflow: hidden;
}
.cesium-container { .cesium-container {
width: 100%; width: 100%;
height: 100vh; height: 100vh;
overflow: hidden; position: absolute;
top: 0;
left: 0;
} }
#cesiumContainer { #cesiumContainer {
...@@ -839,7 +1045,7 @@ onMounted(() => { ...@@ -839,7 +1045,7 @@ onMounted(() => {
pointer-events: auto; pointer-events: auto;
z-index: 9999; z-index: 9999;
top: 100px; top: 100px;
left: 30%; left: 20%;
background-image: url('@/assets/person2.png'); background-image: url('@/assets/person2.png');
background-size: 100% 100%; background-size: 100% 100%;
transform: translate(50%, 50%); transform: translate(50%, 50%);
...@@ -856,7 +1062,7 @@ onMounted(() => { ...@@ -856,7 +1062,7 @@ onMounted(() => {
pointer-events: auto; pointer-events: auto;
z-index: 9999; z-index: 9999;
top: 100px; top: 100px;
left: 30%; left: 20%;
background-image: url('@/assets/person2.png'); background-image: url('@/assets/person2.png');
background-size: 100% 100%; background-size: 100% 100%;
transform: translate(50%, 50%); transform: translate(50%, 50%);
...@@ -873,7 +1079,7 @@ onMounted(() => { ...@@ -873,7 +1079,7 @@ onMounted(() => {
pointer-events: auto; pointer-events: auto;
z-index: 9999; z-index: 9999;
top: 100px; top: 100px;
left: 30%; left: 20%;
background-image: url('@/assets/person2.png'); background-image: url('@/assets/person2.png');
background-size: 100% 100%; background-size: 100% 100%;
transform: translate(50%, 50%); transform: translate(50%, 50%);
...@@ -890,7 +1096,7 @@ onMounted(() => { ...@@ -890,7 +1096,7 @@ onMounted(() => {
pointer-events: auto; pointer-events: auto;
z-index: 9999; z-index: 9999;
top: 100px; top: 100px;
left: 30%; left: 20%;
background-image: url('@/assets/person2.png'); background-image: url('@/assets/person2.png');
background-size: 100% 100%; background-size: 100% 100%;
transform: translate(50%, 50%); transform: translate(50%, 50%);
...@@ -908,7 +1114,7 @@ onMounted(() => { ...@@ -908,7 +1114,7 @@ onMounted(() => {
.title3 { .title3 {
display: flex; display: flex;
align-items: center; align-items: center;
margin: 0px 0px 8px 10px; margin: 0px 0px 8px 0px;
} }
.title4 { .title4 {
...@@ -943,8 +1149,12 @@ span { ...@@ -943,8 +1149,12 @@ span {
.right { .right {
width: 60%; width: 60%;
height: 50%; height: 50%;
margin-right: 20px; /* margin-right: 20px; */
margin-top: 20px; /* margin-top: 20px; */
}
#video {
height: 250px;
} }
.video-top { .video-top {
...@@ -967,7 +1177,6 @@ span { ...@@ -967,7 +1177,6 @@ span {
.n-select { .n-select {
background-image: url('@/assets/multiple-pop.png'); background-image: url('@/assets/multiple-pop.png');
/* background-size: cover; */
background-position: center; background-position: center;
} }
...@@ -1000,37 +1209,320 @@ span { ...@@ -1000,37 +1209,320 @@ span {
:deep(.n-tag .n-tag__border) { :deep(.n-tag .n-tag__border) {
border: none; border: none;
} }
:deep(.n-base-selection-tag-wrapper) { :deep(.n-base-selection-tag-wrapper) {
background: #10273e00; background: #10273e00;
} }
:global(.cesium-select-popup .n-base-select-menu) { /* zhaojunbao */
width: 227px; .top-toolbar {
height: 230px; position: absolute;
color: white !important; top: 0.5rem;
border: none !important; right: 0.5rem;
background-image: url('@/assets/multiple-pop.png') !important; width: 240px;
background-size: 100% 100% !important; height: 0.4rem;
background-color: transparent !important; color: #11e0ff;
z-index: 99999;
display: flex;
align-items: center;
justify-content: space-between;
.split-line {
width: 0.03rem;
height: 100%;
background: #11e0ff;
}
.baojing {
position: relative;
padding-left: 25px;
display: block;
&::before {
content: '';
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
width: 20px;
height: 20px;
background-image: url('@/assets/jinrun/baojing.png');
background-size: contain;
background-repeat: no-repeat;
}
}
.houtaiguanli {
position: relative;
padding-left: 25px;
display: block;
&::before {
content: '';
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
width: 20px;
height: 20px;
background-image: url('@/assets/jinrun/houtai.png');
background-size: contain;
background-repeat: no-repeat;
}
}
} }
:global(.cesium-select-popup .n-base-select-menu .n-base-select-option.n-base-select-option--show-checkmark) { .top,
margin-right: 5px; .bottom,
color: white !important; .left,
.right {
position: absolute;
background-repeat: no-repeat;
} }
:global(.cesium-select-popup .n-base-select-menu .n-base-select-option.n-base-select-option--selected) { .top {
color: #11e0ff !important; top: 0;
width: 100%;
height: 1.25rem;
position: absolute;
.first-image {
width: 100%;
height: 100%;
position: relative;
& > img {
width: 100%;
}
.second-icon {
position: absolute;
top: 30%;
left: 50%;
transform: translate(-50%, -50%);
width: 5.04rem;
/* 可根据实际需要调整大小 */
height: 0.54rem;
/* 可根据实际需要调整大小 */
}
}
} }
:global(.cesium-select-popup.n-base-select-menu) { .bottom {
background-image: url('@/assets/multiple-pop.png') !important; bottom: 0;
color: white !important; left: 0;
border: none !important; width: 100%;
height: 0.4rem;
background-image: url('@/assets/jinrun/bottom.png');
background-size: cover;
}
.left {
top: 0rem;
left: 0;
width: 5.76rem;
height: calc(100vh);
background-size: contain;
background-position-x: left;
background-image: url('@/assets/jinrun/bg-left.png');
}
.right {
top: 0rem;
right: 0;
width: 5.76rem;
height: calc(100vh);
background-image: url('@/assets/jinrun/bg-right.png');
background-size: contain;
background-position-x: right;
}
.toggle-btn {
position: absolute;
top: 50%;
transform: translateY(-50%);
width: 0.71rem;
height: 1.87rem;
background-image: url('@/assets/jinrun/toggle-left.png');
background-size: cover;
background-repeat: no-repeat;
border-radius: 0 10px 10px 0;
cursor: pointer;
z-index: 100;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.3s ease;
&.left-toggle {
left: 5rem;
/* 与左侧模块宽度一致 */
background-image: url('@/assets/jinrun/toggle-left.png');
}
&.left-toggle:hover {
background-image: url('@/assets/jinrun/toggle-left_click.png');
}
&.right-toggle {
right: 5rem;
/* 与左侧模块宽度一致 */
background-image: url('@/assets/jinrun/toggle-right.png');
}
&.right-toggle:hover {
background-image: url('@/assets/jinrun/toggle-right_click.png');
}
&.collapsed {
&.left-toggle {
left: 0.55rem;
border-radius: 0 10px 10px 0;
}
&.right-toggle {
right: 0.55rem;
border-radius: 10px 0 0 10px;
}
}
.btn-arrow1 {
img {
width: 0.18rem;
}
}
.btn-arrow {
width: 10px;
height: 10px;
border-top: 2px solid #fff;
border-right: 2px solid #fff;
transition: transform 0.3s ease;
&::before {
content: '';
position: absolute;
width: 2px;
height: 10px;
background: #fff;
top: -4px;
right: 4px;
}
}
&.left-toggle .btn-arrow {
transform: rotate(135deg);
}
&.right-toggle .btn-arrow {
transform: rotate(-45deg);
}
&.collapsed {
&.left-toggle .btn-arrow {
transform: rotate(-45deg);
}
&.right-toggle .btn-arrow {
transform: rotate(135deg);
}
}
&:hover {
}
}
.slide-left-enter-active,
.slide-left-leave-active {
transition:
transform 0.5s ease,
opacity 0.5s ease;
}
.slide-left-enter-from {
transform: translateX(-100%);
opacity: 0;
}
.slide-left-leave-to {
transform: translateX(-100%);
opacity: 0;
}
.slide-right-enter-active,
.slide-right-leave-active {
transition:
transform 0.5s ease,
opacity 0.5s ease;
}
.slide-right-enter-from {
transform: translateX(100%);
opacity: 0;
}
.slide-right-leave-to {
transform: translateX(100%);
opacity: 0;
}
.left-modules:not(.v-enter-active):not(.v-leave-active).left-toggle:not(.collapsed) {
left: 0;
border-radius: 0 10px 10px 0;
}
.right-modules:not(.v-enter-active):not(.v-leave-active).right-toggle:not(.collapsed) {
right: 0;
border-radius: 10px 0 0 10px;
background: pink;
} }
:global(.cesium-select-popup .n-base-select-menu .n-base-select-option.n-base-select-option--show-checkmark:hover) { .left-modules,
color: #001f3f !important; .right-modules {
margin-right: 5px; width: 4.6rem;
padding-top: 0.95rem;
position: absolute;
}
.left-modules {
left: 0;
margin-left: 0.4rem;
}
.right-modules {
right: 0;
margin-right: 0.4rem;
}
.arrow-font {
width: 20px;
color: #fff;
font-size: 0.18rem;
display: flex;
flex-direction: column;
}
.video-container {
width: 100%;
height: 250px;
border: 1px solid #ccc;
background: #f5f5f5;
position: relative;
}
#divPlugin {
width: 100%;
height: 100%;
}
.status-info {
position: absolute;
top: 10px;
right: 10px;
background: rgba(0, 0, 0, 0.7);
color: white;
padding: 5px 10px;
border-radius: 4px;
font-size: 12px;
} }
</style> </style>
<script setup lang="ts"> <script setup lang="ts">
import { onMounted, onUnmounted, ref, watch } from 'vue'; import { nextTick, onBeforeMount, onMounted, onUnmounted, ref, watch } from 'vue';
import '../../../../Cesium/Widgets/widgets.css'; import '../../../../Cesium/Widgets/widgets.css';
import { useMessage } from 'naive-ui'; import { useMessage } from 'naive-ui';
import { getFenceListsApi, getPointAllPersonApi } from '@/api'; import {
import { create3D } from '@/api/utils/cesium'; getCameraIdApi,
import { getElevationFromRay, getElevationFromRays } from '@/api/utils/cesiumUtil'; getCarPointAllCarApi,
import { cesiumToLongitudeAndLatitude } from '@/api/utils/coordinateUtil'; getCemeraPointApi,
import { getModel } from '@/api/utils/cesiumModel'; getFenceListsApi,
import fullScreen from '@/utils/full'; getHomeCarApi,
import bluePersonIcon from '@/assets/blueperson.png'; getMonitorIdApi,
import redPersonIcon from '../../../assets/redperson.png'; getMonitorPointApi,
import arrowLeftImg from '@/assets/jinrun/arrow-left.png'; getPointAllPersonApi,
import arrowRightImg from '@/assets/jinrun/arrow-right.png'; getPointListApi
import MultiSelect from './appselect.vue'; } from '@/api';
import { iconPoint } from '@/api/utils/home/cesiumPositions'; import { create3D } from '@/api/utils/cesium';
import { getElevationFromRay, getElevationFromRays } from '@/api/utils/cesiumUtil';
let viewer: any = null; import { cesiumToLongitudeAndLatitude } from '@/api/utils/coordinateUtil';
const message = useMessage(); import { getModel } from '@/api/utils/cesiumModel';
let personEntity: any; import { iconPoint } from '@/api/utils/home/cesiumPositions';
let pins: any = []; import { carSpeed } from '@/api/utils/carSpeed';
const full = ref(false); import fullScreen from '@/utils/full';
let entityId: any; import { webVideo } from '@/utils/ai';
const personList = ref([]); import bluePersonIcon from '@/assets/blueperson.png';
const modelData = ref([ import arrowLeftImg from '@/assets/jinrun/arrow-left.png';
[122.04736846370741, 37.48958083145254], import arrowRightImg from '@/assets/jinrun/arrow-right.png';
[122.04760069379522, 37.489226301608184], import redCarIcon from '@/assets/icon15Red.png';
[122.04823299200363, 37.489451482540346], import redVideoIcon from '@/assets/icon16Red.png';
[122.04802271634016, 37.48983410372907], import redBianIcon from '@/assets/icon17Red.png';
[122.04748237248322, 37.49016152294277] import redPersonIcon from '../../../assets/redperson.png';
]); import blueCarIcon from '@/assets/icon15.png';
import blueVideoIcon from '@/assets/icon16.png';
const options = [ import blueBianIcon from '@/assets/icon17.png';
{ import MultiSelect from './appselect.vue';
label: '全选',
value: '1' let viewer: any = null;
}, const message = useMessage();
{ let personEntity: any;
label: '在线监测设备', const pins: any = [];
value: '2' const full = ref(false);
}, let entityId: any;
{ let link: any;
label: '视频监控', let speed = 0;
value: '3' let text = '';
}, const personList = ref([]);
{ const modelData = ref([
label: '人员定位', [122.04736846370741, 37.48958083145254],
value: '4' [122.04760069379522, 37.489226301608184],
}, [122.04823299200363, 37.489451482540346],
{ [122.04802271634016, 37.48983410372907],
label: '车辆定位', [122.04748237248322, 37.49016152294277]
value: '5' ]);
},
{ const options = [
label: '越界开采', {
value: '6' label: '全选',
} value: '1'
]; },
const value = ref(options.map(opt => opt.value)); {
// 监听选中值的变化 label: '在线监测设备',
watch( value: '3'
value, },
(newVal, oldVal) => { {
// 防止无限递归 label: '视频监控',
if (JSON.stringify(newVal) === JSON.stringify(oldVal)) return; value: '2'
},
// 获取除全选外的所有选项值 {
const otherValues = options.slice(1).map(opt => opt.value); label: '人员定位',
// 检查是否选中了所有其他选项 value: '4'
const allOtherSelected = otherValues.every(val => newVal.includes(val)); },
// 检查是否点击了全选 {
const allSelectedNow = newVal.includes('1'); label: '车辆定位',
const allSelectedBefore = oldVal.includes('1'); value: '5'
},
// 点击了全选选项 {
if (allSelectedNow && !allSelectedBefore) { label: '越界开采',
value.value = options.map(opt => opt.value); value: '6'
return;
}
// 取消了全选选项
if (!allSelectedNow && allSelectedBefore) {
// 检查是否所有其他选项都被选中
const allOtherOptionsSelected = otherValues.every(val => newVal.includes(val));
if (allOtherOptionsSelected) {
// 如果所有其他选项都被选中,取消所有选中状态
value.value = [];
} else {
// 如果不是所有其他选项都被选中,只取消全选选项
value.value = newVal.filter(val => val !== '1');
}
return;
}
const someOptionUnselected = oldVal.length > newVal.length;
if (someOptionUnselected && allSelectedNow) {
// 如果取消了某个选项且当前处于全选状态,取消全选,但保留其他选项
value.value = newVal.filter(val => val !== '1');
}
// 选中了所有其他选项,自动选中全选
if (allOtherSelected && !allSelectedNow) {
value.value = options.map(opt => opt.value);
}
// 如果取消了所有选项,清空value
if (newVal.length === 0) {
value.value = [];
} }
}, ];
{ deep: true } const value = ref(options.map(opt => opt.value));
);
const data = ref([]);
// const data = ref([ const datasouce = ref();
// { const fence = ref<any>();
// type: 1, const personShow = ref(false);
// name: '仓房摄像头2', const carShow = ref(false);
// x: 122.04736846370741, const equipmentShow = ref(false);
// y: 37.48958083145254 const videoShow = ref(false);
// }, const treeFence = ref<any>([]);
// {
// type: 2, const wallEntities = ref<any[]>([]);
// name: '边坡表面位移1', const iconEntities = ref<any[]>([]);
// x: 122.04760069379522, const fenceData = ref({
// y: 37.489226301608184 imagePath: '',
// }, imageColor: ''
// {
// type: 3,
// name: '车辆1',
// x: 122.04823299200363,
// y: 37.489451482540346
// },
// {
// type: 4,
// name: '人工1',
// x: 122.04802271634016,
// y: 37.48983410372907
// },
// {
// type: 5,
// name: '人工2',
// x: 122.04748237248322,
// y: 37.49016152294277
// }
// ]);
const data = ref([]);
const position = ref([]);
const heightData = ref([]);
const datasouce = ref();
const fence = ref<any>();
const personShow = ref(false);
const carShow = ref(false);
const equipmentShow = ref(false);
const videoShow = ref(false);
const treeFence = ref<any>([]);
const wallEntities = ref<any[]>([]);
const iconEntities = ref<any[]>([]);
const fenceData = ref({
imagePath: '',
imageColor: ''
});
const formData = ref([]);
// zhaojunbao 开始
// REM自适应配置
const active = ref(false);
const REM_CONFIG = {
// 设计稿宽度
designWidth: 1920,
designHeight: 1080,
// 基准值:1rem = 100px
baseSize: 100
};
// 跳转首页
const navTo = () => {
window.location.href = '/home';
};
/**
* 设置REM单位
* 根据窗口宽度动态计算根元素font-size
*/
const setRemUnit = () => {
const { designWidth, designHeight, baseSize } = REM_CONFIG;
// 获取当前窗口尺寸
const windowWidth = window.innerWidth;
const windowHeight = window.innerHeight;
// 计算宽高缩放比例
const scaleX = windowWidth / designWidth;
const scaleY = windowHeight / designHeight;
// 取较小的缩放比例以适应屏幕,确保内容不会被裁剪
const scale = Math.min(scaleX, scaleY);
// 设置根元素font-size,确保最小为50px(可选)
const fontSize = Math.max(baseSize * scale, 50);
document.documentElement.style.fontSize = `${fontSize}px`;
};
// 控制左右模块显示状态的响应式变量
const isLeftModulesVisible = ref(true);
const isRightModulesVisible = ref(true);
const toggleBothModules = () => {
isLeftModulesVisible.value = !isLeftModulesVisible.value;
isRightModulesVisible.value = !isRightModulesVisible.value;
};
// zhaojunbao 结束
// 模型
function add3dtiles() {
const CesiumConfig = {
defaultAccessToken:
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI2NTE1OTUxOS1jNTc5LTQwNmMtOWU5My1jNTI3NTIyYzAxNTUiLCJpZCI6MjUwODM5LCJpYXQiOjE3Mjk5MjE1MzV9.xromwPD3oA1e0YsWV035DE5KmYvivkC6fxt344vwObA'
};
Cesium.Ion.defaultAccessToken = CesiumConfig.defaultAccessToken;
viewer = new Cesium.Viewer('cesiumContainer', {
geocoder: false,
homeButton: false,
infoBox: false,
animation: false,
fullscreenButton: false,
enableCompass: true, // 启用指南针
enableCompassOuterRing: true, // 启用指南针外环
sceneModePicker: false,
timeline: false,
navigationHelpButton: false,
baseLayerPicker: false,
enableZoomControls: false, // 禁用缩放控件
enableDistanceLegend: false, // 禁用比例尺
selectionIndicator: false
});
viewer.scene.globe.depthTestAgainstTerrain = true;
viewer.cesiumWidget.creditContainer.style.display = 'none';
viewer.cesiumWidget.screenSpaceEventHandler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);
getModel().then(item => {
create3D(viewer, item, 0);
}); });
} const labelData = ref<any>();
// 摄像头 const formData = ref([]);
// 全局保存当前选中窗口
var g_iWndIndex = 0; //可以不用设置这个变量,有窗口参数的接口中,不用传值,开发包会默认使用当前选择窗口 // zhaojunbao 开始
var g_oLocalConfig = null; //本地配置 // REM自适应配置
const active = ref(false);
//错误码 const REM_CONFIG = {
//通用错误 // 设计稿宽度
var ERROR_CODE_UNKNOWN = 1000; //未知错误 designWidth: 1920,
var ERROR_CODE_NETWORKERROR = 1001; //网络错误 designHeight: 1080,
var ERROR_CODE_PARAMERROR = 1002; //缺少插件元素 // 基准值:1rem = 100px
baseSize: 100
//登录模块
var ERROR_CODE_LOGIN_NOLOGIN = 2000; // 未登录
var ERROR_CODE_LOGIN_REPEATLOGIN = 2001; //设备已登录,重复登录
var ERROR_CODE_LOGIN_NOSUPPORT = 2002; //当前设备不支持Digest登录
//预览播放
var ERROR_CODE_PLAY_PLUGININITFAIL = 3000; //插件初始化失败
var ERROR_CODE_PLAY_NOREPEATPLAY = 3001; //当前窗口已经在预览
var ERROR_CODE_PLAY_PLAYBACKABNORMAL = 3002; //回放异常
var ERROR_CODE_PLAY_PLAYBACKSTOP = 3003; //回放停止
var ERROR_CODE_PLAY_NOFREESPACE = 3004; //录像过程中,硬盘容量不足
//对讲
var ERROR_CODE_TALK_FAIL = 5000; //语音对讲失败
let rtsp = {
ip: "192.168.0.17",
user: "admin",
password: "Gemho120611",
port: "80",
channel: "1",
stream: "0.sdp"
}; };
// 跳转首页
const navTo = () => {
window.location.href = '/home';
let arr = ["192.168.0.17", "192.168.0.18", "192.168.0.15"] };
function switchVideo() { /**
let szDeviceIdentify = rtsp.ip + "_" + rtsp.port * 设置REM单位
* 根据窗口宽度动态计算根元素font-size
WebVideoCtrl.I_Stop({ */
szDeviceIdentify: szDeviceIdentify, // 例:192.168.1.64_80 const setRemUnit = () => {
iWndIndex: g_iWndIndex, // 0~35 const { designWidth, designHeight, baseSize } = REM_CONFIG;
success: function () { // 获取当前窗口尺寸
console.log("停播成功"); const windowWidth = window.innerWidth;
// 停完再播 const windowHeight = window.innerHeight;
startPreview();
}, // 计算宽高缩放比例
error: function () { const scaleX = windowWidth / designWidth;
console.log("停播失败,直接销毁插件"); const scaleY = windowHeight / designHeight;
WebVideoCtrl.I_DestroyPlugin();
startPreview() // 取较小的缩放比例以适应屏幕,确保内容不会被裁剪
} const scale = Math.min(scaleX, scaleY);
// 设置根元素font-size,确保最小为50px(可选)
const fontSize = Math.max(baseSize * scale, 50);
document.documentElement.style.fontSize = `${fontSize}px`;
};
// 控制左右模块显示状态的响应式变量
const isLeftModulesVisible = ref(true);
const isRightModulesVisible = ref(true);
const toggleBothModules = () => {
isLeftModulesVisible.value = !isLeftModulesVisible.value;
isRightModulesVisible.value = !isRightModulesVisible.value;
};
// zhaojunbao 结束
// 模型
function add3dtiles() {
const CesiumConfig = {
defaultAccessToken:
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI2NTE1OTUxOS1jNTc5LTQwNmMtOWU5My1jNTI3NTIyYzAxNTUiLCJpZCI6MjUwODM5LCJpYXQiOjE3Mjk5MjE1MzV9.xromwPD3oA1e0YsWV035DE5KmYvivkC6fxt344vwObA'
};
Cesium.Ion.defaultAccessToken = CesiumConfig.defaultAccessToken;
viewer = new Cesium.Viewer('cesiumContainer', {
geocoder: false,
homeButton: false,
infoBox: false,
animation: false,
fullscreenButton: false,
enableCompass: true, // 启用指南针
enableCompassOuterRing: true, // 启用指南针外环
sceneModePicker: false,
timeline: false,
navigationHelpButton: false,
baseLayerPicker: false,
enableZoomControls: false, // 禁用缩放控件
enableDistanceLegend: false, // 禁用比例尺
selectionIndicator: false
});
viewer.scene.globe.depthTestAgainstTerrain = true;
viewer.cesiumWidget.creditContainer.style.display = 'none';
viewer.cesiumWidget.screenSpaceEventHandler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);
getModel().then(item => {
create3D(viewer, item, 0);
}); });
// 含 0 且含 2(闭区间)
const rClosed = Math.random() * 3; // 0 ≤ r < 3
const rClosed2 = Math.floor(rClosed);
rtsp.ip = arr[rClosed2]
login()
} }
// 监听选中值的变化
function login() { watch(
// 初始化插件 value,
WebVideoCtrl.I_InitPlugin({ (newVal, oldVal) => {
szContainerID: "videoLayout", // 防止无限递归
iWndowType: 1, // 改为1表示单个窗口 if (JSON.stringify(newVal) === JSON.stringify(oldVal)) return;
cbSelWnd: function (xmlDoc) {
console.log("选择了窗口:"); // 获取除全选外的所有选项值
}, const otherValues = options.slice(1).map(opt => opt.value);
cbInitPluginComplete: function () { // 检查是否选中了所有其他选项
WebVideoCtrl.I_InsertOBJECTPlugin("videoLayout").then(() => { const allOtherSelected = otherValues.every(val => newVal.includes(val));
console.log("插件初始化成功!"); // 检查是否点击了全选
clickLogin(1) const allSelectedNow = newVal.includes('1');
}, (err) => { const allSelectedBefore = oldVal.includes('1');
console.log("插件初始化失败");
// 点击了全选选项
if (allSelectedNow && !allSelectedBefore) {
value.value = options.map(opt => opt.value);
return;
}
// 取消了全选选项
if (!allSelectedNow && allSelectedBefore) {
// 检查是否所有其他选项都被选中
const allOtherOptionsSelected = otherValues.every(val => newVal.includes(val));
if (allOtherOptionsSelected) {
// 如果所有其他选项都被选中,取消所有选中状态
value.value = [];
} else {
// 如果不是所有其他选项都被选中,只取消全选选项
value.value = newVal.filter(val => val !== '1');
}
return;
}
const someOptionUnselected = oldVal.length > newVal.length;
if (someOptionUnselected && allSelectedNow) {
// 如果取消了某个选项且当前处于全选状态,取消全选,但保留其他选项
value.value = newVal.filter(val => val !== '1');
}
// 选中了所有其他选项,自动选中全选
if (allOtherSelected && !allSelectedNow) {
value.value = options.map(opt => opt.value);
}
// 如果取消了所有选项,清空value
if (newVal.length === 0) {
value.value = [];
}
},
{ deep: true }
);
// 监听选择框的变化
watch(
value,
newValue => {
// 如果选中了"全选",显示所有实体
if (newValue.includes('1')) {
wallEntities.value.forEach(entity => (entity.show = true));
iconEntities.value.forEach(entity => (entity.show = true));
} else {
// 根据选中的选项显示对应实体
wallEntities.value.forEach(entity => {
entity.show = newValue.includes('6'); // 越界开采对应电子围栏
});
iconEntities.value.forEach(entity => {
const type = entity.properties?.type?.getValue();
switch (type) {
case 1: // 在线监测设备
entity.show = newValue.includes('3');
break;
case 2: // 视频监控
entity.show = newValue.includes('4');
break;
case 3: // 车辆定位
entity.show = newValue.includes('2');
break;
case 4: // 人员定位
case 5: // 人员定位
entity.show = newValue.includes('1');
break;
default:
entity.show = false;
}
}); });
} }
}); },
{ immediate: true }
clickLogout() );
async function fenceListGet() {
const res = await getFenceListsApi();
formData.value = res.data.data;
for (const item of res.data.data) {
const positions = item.coordinate.map((item: { xcoordinate: any; ycoordinate: any }) => {
return [item.xcoordinate, item.ycoordinate];
});
const heights: any = [];
for (const data of item.coordinate) {
const cartographic = Cesium.Cartographic.fromDegrees(data.xcoordinate, data.ycoordinate);
const height = await getElevationFromRay(cartographic, viewer);
heights.push(height);
}
electronic(positions, heights, item.rangeType);
}
} }
// 登录 // 电子围栏
function clickLogin(szProtoType) { function electronic(position: any, heightData: any, rangeType: any) {
let szIP = rtsp.ip function map_common_addDatasouce(datasouceName: string) {
let szPort = rtsp.port let datasouce = viewer.dataSources._dataSources.find(t => {
let szUsername = rtsp.user return t && t.name == datasouceName;
let szPassword = rtsp.password });
if (!datasouce) {
if ("" == szIP || "" == szPort) { datasouce = new Cesium.CustomDataSource(datasouceName);
return; viewer.dataSources.add(datasouce);
}
return datasouce;
} }
var szDeviceIdentify = szIP + "_" + szPort; function DynamicWallMaterialProperty(options: any) {
this._definitionChanged = new Cesium.Event();
WebVideoCtrl.I_Login(szIP, szProtoType, szPort, szUsername, szPassword, { this._color = undefined;
timeout: 3000, this._colorSubscription = undefined;
success: function (xmlDoc) { this.color = options.color || Color.BLUE;
console.log("登陆成功"); this.duration = options.duration || 1000;
startPreview(); this.trailImage = options.trailImage;
}, this._time = new Date().getTime();
error: function (oError) { }
if (ERROR_CODE_LOGIN_REPEATLOGIN === status) { function _getDirectionWallShader(options: any) {
console.log(" 已登录过!"); if (options && options.get) {
let materail =
'czm_material czm_getMaterial(czm_materialInput materialInput)\n\
{\n\
czm_material material = czm_getDefaultMaterial(materialInput);\n\
vec2 st = materialInput.st;';
if (options.freely == 'vertical') {
// (由下到上)
materail += `vec4 colorImage = texture(image, vec2(fract(st.s), fract(float(${options.count})*st.t${
options.direction
} time)));\n\ `;
} else { } else {
if (oError.errorCode === 401) { // (逆时针)
console.log(" 登录失败,已自动切换认证方式!"); materail += `vec4 colorImage = texture(image, vec2(fract(float(${options.count})*st.s ${
options.direction
} else { } time), fract(st.t)));\n\ `;
console.log(" 登录失败");
}
} }
// 泛光
materail +=
'vec4 fragColor;\n\
fragColor.rgb = (colorImage.rgb+color.rgb) / 1.0;\n\
fragColor = czm_gammaCorrect(fragColor);\n\
material.diffuse = colorImage.rgb;\n\
material.alpha = colorImage.a;\n\
material.emission = fragColor.rgb;\n\
return material;\n\
}';
return materail;
} }
});
}
// 退出
function clickLogout() {
var szDeviceIdentify = rtsp.ip;
if (null == szDeviceIdentify) {
return;
} }
WebVideoCtrl.I_Logout(szDeviceIdentify).then(() => {
console.log("退出成功"); Object.defineProperties(DynamicWallMaterialProperty.prototype, {
}, () => { isConstant: {
console.log("退出失败"); get() {
return false;
}
},
definitionChanged: {
get() {
return this._definitionChanged;
}
},
color: Cesium.createPropertyDescriptor('color')
}); });
}
const MaterialType = `wallType${Number.parseInt(Math.random() * 1000)}`;
// 开始预览 DynamicWallMaterialProperty.prototype.getType = function (time) {
function startPreview() { return MaterialType;
deviceIdentify = rtsp.ip + "_" + rtsp.port };
WebVideoCtrl.I_StartRealPlay(deviceIdentify, {
iWndIndex: g_iWndIndex, DynamicWallMaterialProperty.prototype.getValue = function (time, result) {
iStreamType: 1, // 主码流 if (!Cesium.defined(result)) {
iChannelID: 1, result = {};
bZeroChannel: false, }
success: function () { result.color = Cesium.Property.getValueOrClonedDefault(this._color, time, Cesium.Color.WHITE, result.color);
showOPInfo(`摄像头 ${cameraIndex} (${deviceIdentify}) 在窗口 ${windowIndex} 预览成功!`); result.image = this.trailImage;
if (this.duration) {
result.time = ((new Date().getTime() - this._time) % this.duration) / this.duration;
}
viewer.scene.requestRender();
return result;
};
DynamicWallMaterialProperty.prototype.equals = function (other) {
return (
this === other ||
(other instanceof DynamicWallMaterialProperty && Cesium.Property.equals(this._color, other._color))
);
};
Cesium.Material._materialCache.addMaterial(MaterialType, {
fabric: {
type: MaterialType,
uniforms: {
color: new Cesium.Color(1.0, 0.0, 0.0, 0.1),
image: Cesium.Material.DefaultImageId,
time: -20
},
source: _getDirectionWallShader({
get: true,
count: 3.0,
freely: 'vertical',
direction: '-'
})
}, },
error: function (err) { translucent(material) {
showOPInfo(`摄像头 ${cameraIndex} (${deviceIdentify}) 在窗口 ${windowIndex} 预览失败:${err ? (err.errorCode + " - " + err.errorMsg) : "未知错误"}`); return true;
} }
}); });
} Cesium.DynamicWallMaterialProperty = DynamicWallMaterialProperty;
// 摄像头
function loadWall() {
// 监听 position.push(position[0]);
// 监听选择框的变化 heightData.push(heightData[0]);
watch(
value, const data = position.map((item: any) => {
newValue => { return item;
// 如果选中了"全选",显示所有实体 });
if (newValue.includes('1')) { const heightMax = heightData.map((item: any) => {
wallEntities.value.forEach(entity => (entity.show = true)); return item;
iconEntities.value.forEach(entity => (entity.show = true)); });
} else {
// 根据选中的选项显示对应实体 const coor = Array.prototype.concat.apply([], data);
wallEntities.value.forEach(entity => {
entity.show = newValue.includes('6'); // 越界开采对应电子围栏 const minHeightList = heightMax.map((item: any) => {
return item + 30;
}); });
iconEntities.value.forEach(entity => { datasouce.value = map_common_addDatasouce('wall');
const type = entity.properties?.type?.getValue();
switch (type) { if (fence.value) {
case 1: // 在线监测设备 if (treeFence.value.length > 0) {
entity.show = newValue.includes('3'); for (const item of treeFence.value) {
break; datasouce.value.entities.remove(item);
case 2: // 视频监控 }
entity.show = newValue.includes('2'); }
break; }
case 3: // 车辆定位
entity.show = newValue.includes('5'); if (rangeType == 1) {
break; fenceData.value = {
case 4: // 人员定位 imagePath: '/src/assets/wallss.png',
case 5: // 人员定位 imageColor: 'Cesium.Color.ORANGE'
entity.show = newValue.includes('4'); };
break; } else if (rangeType == 2) {
default: fenceData.value = {
entity.show = false; imagePath: '/src/assets/walls.png',
imageColor: 'Cesium.Color.CYAN'
};
} else {
fenceData.value = {
imagePath: '/src/assets/wallsRed.png',
imageColor: 'Cesium.Color.RED'
};
}
const entity = datasouce.value.entities.add({
wall: {
positions: Cesium.Cartesian3.fromDegreesArray(coor),
maximumHeights: heightMax,
minimumHeights: minHeightList,
material: new Cesium.DynamicWallMaterialProperty({
trailImage: fenceData.value.imagePath,
color: fenceData.value.imageColor,
duration: 1500
})
} }
}); });
wallEntities.value.push(entity);
// 保存围栏数据用于边界检测
window.fenceData = position;
} }
}, loadWall();
{ immediate: true } }
);
// 点击弹框隐藏
async function fenceListGet() { function videosShow() {
const res = await getFenceListsApi(); if (videoShow.value == true) {
videoShow.value = false;
formData.value = res.data.data; iconShow();
for (const item of res.data.data) {
const positions = item.coordinate.map((item: { xcoordinate: any; ycoordinate: any }) => {
return [item.xcoordinate, item.ycoordinate];
});
const heights: any = [];
for (const data of item.coordinate) {
const cartographic = Cesium.Cartographic.fromDegrees(data.xcoordinate, data.ycoordinate);
const height = await getElevationFromRay(cartographic, viewer);
heights.push(height);
} }
electronic(positions, heights, item.rangeType);
} }
} function equipmentsShow() {
if (equipmentShow.value == true) {
// 电子围栏 equipmentShow.value = false;
function electronic(position: any, heightData: any, rangeType: any) { iconShow();
function map_common_addDatasouce(datasouceName: string) {
let datasouce = viewer.dataSources._dataSources.find(t => {
return t && t.name == datasouceName;
});
if (!datasouce) {
datasouce = new Cesium.CustomDataSource(datasouceName);
viewer.dataSources.add(datasouce);
} }
return datasouce;
} }
function carsShow() {
function DynamicWallMaterialProperty(options: any) { if (carShow.value == true) {
this._definitionChanged = new Cesium.Event(); carShow.value = false;
this._color = undefined; iconShow();
this._colorSubscription = undefined; }
this.color = options.color || Color.BLUE;
this.duration = options.duration || 1000;
this.trailImage = options.trailImage;
this._time = new Date().getTime();
} }
function _getDirectionWallShader(options: any) { function personsShow() {
if (options && options.get) { if (personShow.value == true) {
let materail = personShow.value = false;
'czm_material czm_getMaterial(czm_materialInput materialInput)\n\ iconShow();
{\n\
czm_material material = czm_getDefaultMaterial(materialInput);\n\
vec2 st = materialInput.st;';
if (options.freely == 'vertical') {
// (由下到上)
materail += `vec4 colorImage = texture(image, vec2(fract(st.s), fract(float(${options.count})*st.t${
options.direction
} time)));\n\ `;
} else {
// (逆时针)
materail += `vec4 colorImage = texture(image, vec2(fract(float(${options.count})*st.s ${
options.direction
} time), fract(st.t)));\n\ `;
}
// 泛光
materail +=
'vec4 fragColor;\n\
fragColor.rgb = (colorImage.rgb+color.rgb) / 1.0;\n\
fragColor = czm_gammaCorrect(fragColor);\n\
material.diffuse = colorImage.rgb;\n\
material.alpha = colorImage.a;\n\
material.emission = fragColor.rgb;\n\
return material;\n\
}';
return materail;
} }
} }
Object.defineProperties(DynamicWallMaterialProperty.prototype, { function iconShow() {
isConstant: { for (const item of pins) {
get() { if (item.type == 1) {
return false; item.image = bluePersonIcon;
} } else if (item.type == 2) {
}, item.image = blueCarIcon;
definitionChanged: { } else if (item.type == 3) {
get() { item.image = blueBianIcon;
return this._definitionChanged; } else {
item.image = blueVideoIcon;
} }
},
color: Cesium.createPropertyDescriptor('color')
});
const MaterialType = `wallType${Number.parseInt(Math.random() * 1000)}`;
DynamicWallMaterialProperty.prototype.getType = function (time) {
return MaterialType;
};
DynamicWallMaterialProperty.prototype.getValue = function (time, result) {
if (!Cesium.defined(result)) {
result = {};
} }
result.color = Cesium.Property.getValueOrClonedDefault(this._color, time, Cesium.Color.WHITE, result.color); iconPoint(viewer, pins);
result.image = this.trailImage; }
if (this.duration) {
result.time = ((new Date().getTime() - this._time) % this.duration) / this.duration; // 设置员工类型
} function getPersonTypeName(type: number): string {
viewer.scene.requestRender(); switch (type) {
return result; case 1:
}; return '员工';
case 2:
DynamicWallMaterialProperty.prototype.equals = function (other) { return '访客';
return ( default:
this === other || return '没有该类型';
(other instanceof DynamicWallMaterialProperty && Cesium.Property.equals(this._color, other._color))
);
};
Cesium.Material._materialCache.addMaterial(MaterialType, {
fabric: {
type: MaterialType,
uniforms: {
color: new Cesium.Color(1.0, 0.0, 0.0, 0.1),
image: Cesium.Material.DefaultImageId,
time: -20
},
source: _getDirectionWallShader({
get: true,
count: 3.0,
freely: 'vertical',
direction: '-'
})
},
translucent(material) {
return true;
} }
}); }
Cesium.DynamicWallMaterialProperty = DynamicWallMaterialProperty;
async function setTimePerson() {
function loadWall() { const res = await getPointAllPersonApi();
position.push(position[0]); for (const item of pins) {
heightData.push(heightData[0]); const pin = res.data.data.find((personData: any) => personData.cardId == item.id);
if (pin) {
const data = position.map((item: any) => { personShow.value = false;
return item; item.image = bluePersonIcon;
}); item.position = {
const heightMax = heightData.map((item: any) => { lon: pin.lon,
return item; lat: pin.lat
}); };
const coor = Array.prototype.concat.apply([], data);
const minHeightList = heightMax.map((item: any) => {
return item + 30;
});
datasouce.value = map_common_addDatasouce('wall');
if (fence.value) {
if (treeFence.value.length > 0) {
for (const item of treeFence.value) {
datasouce.value.entities.remove(item);
}
} }
} }
const carRes = await getCarPointAllCarApi();
if (rangeType == 1) { for (const item of pins) {
fenceData.value = { const pin = carRes.data.data.find((carData: any) => carData.carNumber == item.id);
imagePath: '/src/assets/wallss.png', if (pin) {
imageColor: 'Cesium.Color.ORANGE' carShow.value = false;
}; item.image = blueCarIcon;
} else if (rangeType == 2) { item.position = {
fenceData.value = { lon: pin.lon,
imagePath: '/src/assets/walls.png', lat: pin.lat
imageColor: 'Cesium.Color.CYAN' };
};
} else {
fenceData.value = {
imagePath: '/src/assets/wallsRed.png',
imageColor: 'Cesium.Color.RED'
};
}
const entity = datasouce.value.entities.add({
wall: {
positions: Cesium.Cartesian3.fromDegreesArray(coor),
maximumHeights: heightMax,
minimumHeights: minHeightList,
material: new Cesium.DynamicWallMaterialProperty({
trailImage: fenceData.value.imagePath,
color: fenceData.value.imageColor,
duration: 1500
})
} }
});
wallEntities.value.push(entity);
// 保存围栏数据用于边界检测
window.fenceData = position;
}
loadWall();
}
// 点击弹框隐藏
function videosShow() {
if (videoShow.value == true) {
videoShow.value = false;
}
}
function equipmentsShow() {
if (equipmentShow.value == true) {
equipmentShow.value = false;
}
}
function carsShow() {
if (carShow.value == true) {
carShow.value = false;
}
}
function personsShow() {
if (personShow.value == true) {
personShow.value = false;
}
}
// 设置员工类型
function getPersonTypeName(type: number): string {
switch(type) {
case 1:
return '员工';
case 2:
return '访客';
default:
return '没有该类型';
}
}
onMounted(() => {
add3dtiles();
setTimeout(async () => {
// electronic();
fenceListGet();
let res = await getPointAllPersonApi();
data.value = res.data.data;
iconPoint(viewer,data,'person_').then(result => {
pins = result;
console.log('111',pins);
});
}, 2000);
// zhaojunbao 开始
// 初始化REM自适应
setRemUnit();
// 监听窗口大小变化
window.addEventListener('resize', setRemUnit);
// zhaojunbao 结束
let currentSelectedPerson = null;
const handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
// 鼠标点击事件
handler.setInputAction(function (click: any) {
console.log('222',pins);
const pickedObject = viewer.scene.pick(click.position);
entityId = pickedObject.id.id;
if (!pickedObject.collection) {
videoShow.value = false;
equipmentShow.value = false;
carShow.value = false;
personShow.value = false;
return;
} }
if (Cesium.defined(pickedObject) && pickedObject.id) { iconPoint(viewer, pins);
const pin = pins.find(p => p.entity === pickedObject.id); }
console.log('333',pin); setInterval(setTimePerson, 10 * 1000);
if (pin.type == 1) {
videoShow.value = true; onMounted(async () => {
} else if (pin.type == 2) { add3dtiles();
equipmentShow.value = true; setTimeout(async () => {
} else if (pin.type == 3) { fenceListGet();
carShow.value = true;
} else { const res = await getPointAllPersonApi();
personList.value = []; const personData = res.data.data;
if(typeof entityId == 'string' && entityId.startsWith('person_')) { personData.map(item => {
viewer.entities.values.forEach((entity:any) => { pins.push({
if(typeof entity.id === 'string' && entity.id.startsWith('person_')) { id: item.cardId,
entity.billboard.image = bluePersonIcon; name: item.realName,
} type: 1,
}); image: bluePersonIcon,
position: {
const clickedEntity = viewer.entities.getById(entityId); lon: item.lon,
if(clickedEntity) { lat: item.lat
clickedEntity.billboard.image = redPersonIcon; },
currentSelectedPerson = clickedEntity; data: item,
} entity: null
});
});
// 获取并显示车辆数据,使用不同的前缀
const resCar = await getCarPointAllCarApi();
const carData = resCar.data.data;
carData.map(item => {
pins.push({
id: item.carNumber,
name: item.carNumber,
type: 2,
image: blueCarIcon,
position: {
lon: item.lon,
lat: item.lat
},
data: item,
entity: null
});
});
// 获取在线监测
const resPoint = await getMonitorPointApi();
const pointData = resPoint.data.data;
pointData.map(item => {
pins.push({
id: item.id,
type: 3,
name: item.equipname,
image: blueBianIcon,
position: {
lon: item.longitude,
lat: item.latitude
},
data: item,
entity: null,
label: null
});
});
// 获取视频监控信息
const resVideo = await getCemeraPointApi();
const videoData = resVideo.data.data;
videoData.map(item => {
pins.push({
id: item.id,
name: item.cameraName,
type: 4,
image: blueVideoIcon,
position: {
lon: item.lon,
lat: item.lat
},
data: item,
entity: null
});
});
iconPoint(viewer, pins).then(result => {
console.log(result);
});
}, 2000);
// setTimePerson();
setRemUnit();
// 监听窗口大小变化
window.addEventListener('resize', setRemUnit);
// zhaojunbao 结束
const handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
handler.setInputAction(async function (click: any) {
const pickedObject = viewer.scene.pick(click.position);
for (const item of pins) {
if (item.type == 1) {
item.image = bluePersonIcon;
} else if (item.type == 2) {
item.image = blueCarIcon;
} else if (item.type == 3) {
item.image = blueBianIcon;
} else {
item.image = blueVideoIcon;
}
}
if (Cesium.defined(pickedObject) && Cesium.defined(pickedObject.id)) {
const pin = pins.find(item => item.entity === pickedObject.id);
if (pin.type == 1) {
equipmentShow.value = false;
videoShow.value = false;
carShow.value = false;
personShow.value = true; personShow.value = true;
console.log(pickedObject.id.personData); labelData.value = pin.data;
if (pickedObject.id.personData) {
pin.image = redPersonIcon;
} else if (pin.type == 2) {
personList.value.push({ // 车
personId: pickedObject.id.personData.info.personId, equipmentShow.value = false;
realName: pickedObject.id.personData.info.realName, videoShow.value = false;
remark: pickedObject.id.personData.info.remark, personShow.value = false;
phone: pickedObject.id.personData.info.phone, carShow.value = true;
deptName: pickedObject.id.personData.info.deptName, const res = await getHomeCarApi(pin.id);
personType: pickedObject.id.personData.info.personType, console.log(res);
})
if (res.data.code == 200) {
speed = res.data.data.point ? carSpeed(res.data.data) : 0;
labelData.value = res.data.data;
link = `${labelData.value.ipAddress}?lang=zh&devIdno=${labelData.value.cameraNo}&account=${labelData.value.username}&password=${labelData.value.password}&channel=1`;
}
pin.image = redCarIcon;
} else if (pin.type == 3) {
// 监测设备
videoShow.value = false;
carShow.value = false;
personShow.value = false;
equipmentShow.value = true;
const res = await getMonitorIdApi(pin.id);
if (res.data.code == 200) {
if (res.data.data.devicetype == 3) {
text = '表面位移';
} else if (res.data.data.devicetype == 6) {
text = '降雨量';
}
labelData.value = res.data.data;
} }
pin.image = redBianIcon;
} else { } else {
personList.value = []; // 摄像头
equipmentShow.value = false;
videoShow.value = true;
carShow.value = false;
personShow.value = false; personShow.value = false;
videoShow.value = true;
if (personShow.value == false) { const res = await getCameraIdApi(pin.id);
const clickedEntity = viewer.entities.getById(entityId); if (res.data.code == 200) {
clickedEntity.billboard.image = bluePersonIcon; labelData.value = res.data.data;
console.log(labelData.value);
const webRtcServrce = ref();
nextTick(() => {
webRtcServrce.value = new WebRtcStreamer('video', `${location.protocol}//` + `192.168.2.53:8000`);
webRtcServrce.value.connect(res.data.data.videoStream);
});
} }
pin.image = redVideoIcon;
} }
iconPoint(viewer, pins);
} else {
equipmentShow.value = false;
videoShow.value = false;
carShow.value = false;
personShow.value = false;
iconPoint(viewer, pins);
} }
} else { }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
videoShow.value = false; });
equipmentShow.value = false;
carShow.value = false; onUnmounted(() => {
personShow.value = false; // 清理Cesium资源
if (viewer) {
viewer.destroy();
viewer = null;
} }
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
}); // 移除窗口大小变化监听
window.removeEventListener('resize', setRemUnit);
onUnmounted(() => {
// 清理Cesium资源 // 移除html元素style属性中的font-size
if (viewer) { document.documentElement.style.fontSize = '';
viewer.destroy(); });
viewer = null; </script>
}
<template>
// 移除窗口大小变化监听 <div class="wrapper">
window.removeEventListener("resize", setRemUnit); <div class="top-toolbar">
<div class="baojing">
// 移除html元素style属性中的font-size 声光报警
document.documentElement.style.fontSize = ''; <NSwitch v-model:value="active" />
}); </div>
</script>
<!-- <i class="split-line"></i> -->
<template> <div class="split-line"></div>
<div class="wrapper"> <div class="houtaiguanli" @click="navTo">后台管理</div>
<div class="top-toolbar">
<div class="baojing">
声光报警
<NSwitch v-model:value="active" />
</div> </div>
<!-- cesium 容器 -->
<!-- <i class="split-line"></i> --> <div class="cesium-container">
<div class="split-line"></div> <div id="cesiumContainer">
<div class="houtaiguanli" @click="navTo">后台管理</div> <!-- 选择框 -->
</div> <MultiSelect v-model="value" :options="options" style="position: fixed; z-index: 999; top: 100px; left: 63%" />
<!-- cesium 容器 --> <!-- 人员信息弹框 -->
<div class="cesium-container"> <div v-if="personShow == true" class="personMessage">
<div id="cesiumContainer"> <div style="display: flex; justify-content: flex-start; align-items: center; margin-bottom: 10px">
<!-- 选择框 --> <div style="width: 90%; margin: 0; font-size: 16px">
<MultiSelect v-model="value" :options="options" style="position: fixed; z-index: 999; top: 100px; left: 63%" /> <span>人员信息</span>
<!-- 人员信息弹框 --> <div class="person1"></div>
<div v-if="personShow == true" class="personMessage"> </div>
<div style="display: flex; justify-content: flex-start; align-items: center; margin-bottom: 10px">
<div style="width: 90%; margin: 0; font-size: 16px"> <button
<span>人员信息</span> id="close-info"
<div class="person1"></div> style="background: none; border: none; color: white; cursor: pointer; font-size: 18px; margin-left: 10px"
@click="personsShow()"
>
&times;
</button>
</div> </div>
<div style="line-height: 1.8">
<button <p class="title1">
id="close-info" <strong class="title2">姓名:</strong>
style="background: none; border: none; color: white; cursor: pointer; font-size: 18px; margin-left: 10px" {{ labelData.realName }}
@click="personsShow()" </p>
> <p class="title1">
&times; <strong class="title2">定位卡号:</strong>
</button> {{ labelData.cardId }}
</div> </p>
<div style="line-height: 1.8" v-for="item in personList"> <p class="title1">
<p class="title1"> <strong class="title2">人员类型:</strong>
<strong class="title2">姓名:</strong> {{ getPersonTypeName(labelData.personType) }}
{{item.realName}} </p>
</p> <p class="title1">
<p class="title1"> <strong class="title2">电话:</strong>
<strong class="title2">定位卡号:</strong> {{ labelData.phone }}
{{item.remark}} </p>
</p> <p class="title1">
<p class="title1"> <strong class="title2">部门:</strong>
<strong class="title2">人员类型:</strong> {{ labelData.deptName }}
{{ getPersonTypeName(item.personType) }} </p>
</p>
<p class="title1">
<strong class="title2">电话:</strong>
{{ item.phone}}
</p>
<p class="title1">
<strong class="title2">部门:</strong>
{{ item.deptName}}
</p>
</div>
</div>
<!-- 车辆信息 -->
<div v-if="carShow == true" class="carMessage">
<div style="display: flex; justify-content: flex-start; align-items: center; margin-bottom: 10px">
<div style="width: 90%; margin: 0; font-size: 16px">
<span>车辆信息</span>
<div class="person1"></div>
</div> </div>
<button
id="close-info"
style="background: none; border: none; color: white; cursor: pointer; font-size: 18px; margin-left: 10px"
@click="carsShow()"
>
&times;
</button>
</div> </div>
<div style="line-height: 1.8; display: flex; justify-content: space-between"> <!-- 车辆信息 -->
<div class="car-left"> <div v-if="carShow == true" class="carMessage">
<div class="left-top"> <div style="display: flex; justify-content: flex-start; align-items: center; margin-bottom: 10px">
<p class="title1"> <div style="width: 90%; margin: 0; font-size: 16px">
<strong class="title2">车牌号:</strong> <span>车辆信息</span>
鲁K:534435 <div class="person1"></div>
</p>
<p class="title1">
<strong class="title2">车队名称:</strong>
KC001
</p>
<p class="title1">
<strong class="title2">当前车速:</strong>
25km/h
</p>
<p class="title1">
<strong class="title2">车辆类型:</strong>
卡车
</p>
</div>
<div class="left-center"></div>
<div class="left-bottom">
<p class="title1">
<strong class="title2">司机姓名:</strong>
张喂
</p>
<p class="title1">
<strong class="title2">工作开始时间:</strong>
8:30
</p>
<p class="title1">
<strong class="title2">工作时长:</strong>
3H
</p>
<p class="title1">
<strong class="title2">终端设备编号:</strong>
ZD000001
</p>
</div> </div>
</div> <button
<div class="car-right"> id="close-info"
<!-- style="background: none; border: none; color: white; cursor: pointer; font-size: 18px; margin-left: 10px"
<video id="video" controls autoplay muted playsinline width="100%" height="100%" @click="carsShow()"
style="object-fit: fill; z-index: 1;"></video>
-->
<div
:style="
full
? {
border: '1px solid #ccc',
padding: '2px',
position: 'fixed',
top: 0,
left: 0,
width: '100vw',
height: '100px',
zIndex: '99'
}
: {
padding: '2px',
height: '250px !important',
border: ' 1px solid #ccc',
position: 'relative',
margin: '0px 10px 0px 0px'
}
"
> >
<div style="position: absolute; bottom: 5px; right: 5px; width: 40px; height: 40px; cursor: pointer"> &times;
<icon-gridicons-fullscreen-exit </button>
v-if="full" </div>
color="#11e0ff" <div style="line-height: 1.8; display: flex; justify-content: space-between">
font-size="30" <div class="car-left">
@click="full = fullScreen(full)" <div class="left-top">
/> <p class="title1">
<icon-gridicons-fullscreen v-else font-size="30" color="#11e0ff" @click="full = fullScreen(full)" /> <strong class="title2">车牌号:</strong>
{{ labelData.carNumber || '暂无数据' }}
</p>
<p class="title1">
<strong class="title2">车队名称:</strong>
{{ labelData.teamName || '暂无数据' }}
</p>
<p class="title1">
<strong class="title2">当前车速:</strong>
{{ speed }} km/h
</p>
<p class="title1">
<strong class="title2">车辆类型:</strong>
{{ labelData.carType || '暂无数据' }}
</p>
</div> </div>
<canvas id="canvas-4" style="width: 100%; height: 100%" width="800" height="600"></canvas> <div class="left-center"></div>
<div class="left-bottom">
<p class="title1">
<strong class="title2">司机姓名:</strong>
{{ labelData.driverName || '暂无数据' }}
</p>
<p class="title1">
<strong class="title2">工作开始时间:</strong>
{{ labelData.workStartTime || '暂无数据' }}
</p>
<p class="title1">
<strong class="title2">工作时长:</strong>
{{ labelData.workTime || '暂无数据' }}
</p>
<p class="title1">
<strong class="title2">终端设备编号:</strong>
{{ labelData.terminalNumber || '暂无数据' }}
</p>
</div>
</div>
<div class="car-right">
<iframe
allowfullscreen="true"
allowtransparency="true"
allow="autoplay"
scrolling="no"
:src="link"
width="100%"
height="100%"
frameborder="0"
style="padding-right: 20px"
></iframe>
<!-- '${res.ipAddress}?lang=zh&devIdno=${res.cameraNo}&account=${res.username}&password=${res.password}&channel=1' -->
</div> </div>
</div> </div>
</div> </div>
</div> <!-- 在线检测设备信息 -->
<!-- 在线检测设备信息 --> <div v-if="equipmentShow == true" class="equipmentMessage">
<div v-if="equipmentShow == true" class="equipmentMessage"> <div style="display: flex; justify-content: flex-start; align-items: center; margin-bottom: 10px">
<div style="display: flex; justify-content: flex-start; align-items: center; margin-bottom: 10px"> <div style="width: 90%; margin: 0; font-size: 16px">
<div style="width: 90%; margin: 0; font-size: 16px"> <span>在线检测设备信息</span>
<span>在线检测设备信息</span> <div class="person1"></div>
<div class="person1"></div> </div>
<button
id="close-info"
style="background: none; border: none; color: white; cursor: pointer; font-size: 18px; margin-left: 10px"
@click="equipmentsShow()"
>
&times;
</button>
</div> </div>
<button <div style="line-height: 1.8">
id="close-info" <p class="title1">
style="background: none; border: none; color: white; cursor: pointer; font-size: 18px; margin-left: 10px" <strong class="title2">设备名称:</strong>
@click="equipmentsShow()" {{ labelData.equipname }}
> </p>
&times; <p class="title1">
</button> <strong class="title2">设备状态:</strong>
</div> {{ labelData.dataStatus === 0 ? '在线' : '离线' }}
<div style="line-height: 1.8"> </p>
<p class="title1"> <p class="title1">
<strong class="title2">设备名称:</strong> <strong class="title2">设备类型:</strong>
设备表面位移01 {{ text }}
</p> </p>
<p class="title1"> <p class="title1">
<strong class="title2">设备状态:</strong> <strong class="title2">监测值:</strong>
在线/离线 {{ labelData.value }}
</p> </p>
<p class="title1"> <p class="title1">
<strong class="title2">设备类型:</strong> <strong class="title2">监测时间:</strong>
表面位移/降雨量/环境监测 {{ labelData.time }}
</p> </p>
<p class="title1"> <p class="title1">
<strong class="title2">监测值:</strong> <strong class="title2">数据状态:</strong>
0.004mm {{ labelData.onlineStatus === 0 ? '正常' : '蓝色报警' }}
</p> </p>
<p class="title1">
<strong class="title2">监测时间:</strong>
2025-10 10:10:10
</p>
<p class="title1">
<strong class="title2">数据状态:</strong>
正常
</p>
</div>
</div>
<!-- 视频监控信息 -->
<div v-if="videoShow == true" class="videoMessage">
<div style="display: flex; justify-content: flex-start; align-items: center; margin-bottom: 10px">
<div style="width: 90%; margin: 0; font-size: 16px">
<span>视频监控信息</span>
<div class="person1"></div>
</div> </div>
<button
id="close-info"
style="background: none; border: none; color: white; cursor: pointer; font-size: 18px; margin-left: 10px"
@click="videosShow()"
>
&times;
</button>
</div> </div>
<div style="line-height: 1.8; display: flex; flex-direction: column; flex-wrap: nowrap"> <!-- 视频监控信息 -->
<div class="video-top"> <div v-if="videoShow == true" class="videoMessage">
<div class="title3"> <div style="display: flex; justify-content: flex-start; align-items: center; margin-bottom: 10px">
<strong class="title2">● 摄像头名称:</strong> <div style="width: 90%; margin: 0; font-size: 16px">
排土场入口 <span>视频监控信息</span>
<div class="person1"></div>
</div> </div>
<div class="title3"> <button
<strong class="title4">● 区域名称:</strong> id="close-info"
排土场背部 style="background: none; border: none; color: white; cursor: pointer; font-size: 18px; margin-left: 10px"
</div> @click="videosShow()"
<div class="title3">
<strong class="title4">● 设备状态:</strong>
在线/离线
</div>
</div>
<div class="video-bottom">
<!-- <NButton @click="login()">登陆</NButton>
<NButton @click="switchVideo()">切换视频流</NButton>
<div id="videoLayout" style="width: 500px; height: 250px; border: 1px solid red;"></div> -->
<div
:style="
full
? {
border: '1px solid #ccc',
padding: '2px',
position: 'fixed',
top: 0,
left: 0,
width: '100vw',
height: '100px',
zIndex: '99'
}
: {
padding: '2px',
height: '250px !important',
border: ' 1px solid #ccc',
position: 'relative'
}
"
> >
<div style="position: absolute; bottom: 5px; right: 5px; width: 40px; height: 40px; cursor: pointer"> &times;
<icon-gridicons-fullscreen-exit </button>
v-if="full" </div>
color="#11e0ff" <div style="line-height: 1.8; display: flex; flex-direction: column; flex-wrap: nowrap">
font-size="30" <div class="video-top">
@click="full = fullScreen(full)" <div class="title3">
/> <strong class="title2">● 摄像头名称:</strong>
<icon-gridicons-fullscreen v-else font-size="30" color="#11e0ff" @click="full = fullScreen(full)" /> {{ labelData.areaName }}
</div>
<div class="title3">
<strong class="title4">● 区域名称:</strong>
{{ labelData.cameraName }}
</div> </div>
<canvas id="canvas-4" style="width: 100%; height: 100%" width="800" height="600"></canvas> <div class="title3">
<strong class="title4">● 设备状态:</strong>
{{ labelData.status === 0 ? '在线' : '离线' }}
</div>
</div>
<div class="video-bottom">
<video
id="video"
controls
autoplay
muted
playsinline
width="100%"
height="100%"
style="object-fit: fill; z-index: 1"
></video>
</div> </div>
</div> </div>
</div> </div>
<!-- </div> -->
</div> </div>
<!-- </div> -->
</div> </div>
</div> </div>
</div>
<div class="top">
<div class="top"> <div class="first-image">
<div class="first-image"> <img src="@/assets/jinrun/top.png" alt="" srcset="" />
<img src="@/assets/jinrun/top.png" alt="" srcset="" /> <div class="second-icon">
<div class="second-icon"> <img src="@/assets/jinrun/title.png" alt="" />
<img src="@/assets/jinrun/title.png" alt="" /> </div>
</div> </div>
</div> </div>
</div> <div class="bottom"></div>
<div class="bottom"></div> <div v-show="isLeftModulesVisible" class="left"></div>
<div class="left"></div> <div v-show="isRightModulesVisible" class="right"></div>
<div class="right"></div>
<!-- 非cesium相关 开始 -->
<!-- 非cesium相关 开始 -->
<!-- 左侧收起按钮 -->
<!-- 左侧收起按钮 --> <div class="toggle-btn left-toggle" :class="{ collapsed: !isLeftModulesVisible }" @click="toggleBothModules">
<div class="toggle-btn left-toggle" :class="{ collapsed: !isLeftModulesVisible }" @click="toggleBothModules"> <div class="btn-arrow1">
<div class="btn-arrow1"> <div>
<div> <img :src="isLeftModulesVisible ? arrowLeftImg : arrowRightImg" alt="" srcset="" />
<img :src="isLeftModulesVisible ? arrowLeftImg : arrowRightImg" alt="" srcset="" /> <br />
<br /> <div class="arrow-font">
<!-- {{ isLeftModulesVisible ? '收起' : '展开' }}
<span class="arrow-font">{{ isLeftModulesVisible ? "" : "" }}</span> </div>
<br />
<span class="arrow-font">{{ isLeftModulesVisible ? "" : "" }}</span>
-->
<div class="arrow-font">
{{ isLeftModulesVisible ? '收起' : '展开' }}
</div> </div>
</div> </div>
</div> </div>
</div>
<!-- 右侧收起按钮 -->
<!-- 右侧收起按钮 --> <div class="toggle-btn right-toggle" :class="{ collapsed: !isRightModulesVisible }" @click="toggleBothModules">
<div class="toggle-btn right-toggle" :class="{ collapsed: !isRightModulesVisible }" @click="toggleBothModules"> <!-- <div class="btn-arrow1"><img src="@/assets/jinrun/arrow-right.png" alt="" srcset=""><br><br></div> -->
<!-- <div class="btn-arrow1"><img src="@/assets/jinrun/arrow-right.png" alt="" srcset=""><br><br></div> --> <div class="btn-arrow1">
<div class="btn-arrow1"> <div>
<div> <img :src="isLeftModulesVisible ? arrowRightImg : arrowLeftImg" alt="" srcset="" />
<img :src="isLeftModulesVisible ? arrowRightImg : arrowLeftImg" alt="" srcset="" /> <br />
<br /> <div class="arrow-font">
<!-- {{ isLeftModulesVisible ? '收起' : '展开' }}
<span class="arrow-font">{{ isLeftModulesVisible ? "" : "" }}</span> </div>
<br />
<span class="arrow-font">{{ isLeftModulesVisible ? "" : "" }}</span>
-->
<div class="arrow-font">
{{ isLeftModulesVisible ? '收起' : '展开' }}
</div> </div>
</div> </div>
</div> </div>
</div>
<!-- 左侧模块容器 -->
<!-- 左侧模块容器 --> <Transition name="slide-left">
<transition name="slide-left"> <div v-show="isLeftModulesVisible" class="left-modules">
<div class="left-modules" v-show="isLeftModulesVisible"> <LeftDeviceStatus />
<LeftDeviceStatus /> <LeftRainfallTrend />
<LeftRainfallTrend /> <LeftOnlineMonitor />
<LeftOnlineMonitor /> </div>
</div> </Transition>
</transition>
<!-- 右侧模块容器 -->
<!-- 右侧模块容器 --> <Transition name="slide-right">
<transition name="slide-right"> <div v-show="isRightModulesVisible" class="right-modules">
<div class="right-modules" v-show="isRightModulesVisible"> <RightAiWarning />
<RightAiWarning /> <RightEnvMonitor />
<RightEnvMonitor /> <RightTodayAlarm />
<RightTodayAlarm /> </div>
</div> </Transition>
</transition> <!-- 非cesium相关 结束 -->
<!-- 非cesium相关 结束 --> </template>
</template>
<style scoped>
<style scoped> html,
html, body { body {
width: 100%; width: 100%;
height: 100%;
overflow: hidden;
}
.cesium-container {
width: 100%;
height: 100vh;
position: absolute;
top: 0;
left: 0;
}
#cesiumContainer {
width: 100%;
height: 100%;
}
.personMessage {
width: 450px;
height: 250px;
position: absolute;
padding: 15px 20px;
color: white;
font-family: sans-serif;
font-size: 14px;
pointer-events: auto;
z-index: 9999;
top: 100px;
left: 30%;
background-image: url('@/assets/person2.png');
background-size: 100% 100%;
transform: translate(50%, 50%);
}
.carMessage {
width: 600px;
height: 380px;
position: absolute;
padding: 15px 20px;
color: white;
font-family: sans-serif;
font-size: 14px;
pointer-events: auto;
z-index: 9999;
top: 100px;
left: 30%;
background-image: url('@/assets/person2.png');
background-size: 100% 100%;
transform: translate(50%, 50%);
}
.equipmentMessage {
width: 450px;
height: 290px;
position: absolute;
padding: 15px 20px;
color: white;
font-family: sans-serif;
font-size: 14px;
pointer-events: auto;
z-index: 9999;
top: 100px;
left: 30%;
background-image: url('@/assets/person2.png');
background-size: 100% 100%;
transform: translate(50%, 50%);
}
.videoMessage {
width: 680px;
height: 380px;
position: absolute;
padding: 15px 20px;
color: white;
font-family: sans-serif;
font-size: 14px;
pointer-events: auto;
z-index: 9999;
top: 100px;
left: 30%;
background-image: url('@/assets/person2.png');
background-size: 100% 100%;
transform: translate(50%, 50%);
}
.title1 {
margin-top: 5px;
}
.title2 {
color: #29d7fb;
margin-right: 10px;
}
.title3 {
display: flex;
align-items: center;
margin: 0px 0px 8px 10px;
}
.title4 {
color: #29d7fb;
margin-right: 10px;
margin-left: 20px;
}
span {
position: absolute;
z-index: 4;
left: 30px;
top: 10px;
}
.person1 {
width: 85%;
height: 40px;
background-image: url('@/assets/person1.png');
background-size: 100% 100%;
position: absolute;
left: 6px;
top: 20px;
}
.left-center {
width: 100%;
height: 10px;
border-bottom: 1px solid #147f9c;
}
.right {
width: 60%;
height: 50%;
margin-right: 20px;
/* margin-top: 20px; */
}
.video-top {
width: 100%;
height: 50%;
display: flex;
flex-direction: row;
flex-wrap: nowrap;
}
.video-bottom {
margin-right: 20px;
}
.select {
width: 100%;
border: none;
background-image: url('@/assets/multiple-pop.png');
}
.n-select {
background-image: url('@/assets/multiple-pop.png');
background-position: center;
}
.n-select .n-select-trigger {
background-color: transparent;
}
.n-select .n-select-menu {
background-color: transparent;
}
:deep(.n-base-selection .n-base-selection-tags) {
background-color: transparent !important;
}
:deep(.n-base-selection .n-base-selection-label .n-base-selection-input .n-base-selection-input__content) {
color: white !important;
}
:deep(.n-base-selection .n-base-selection__border, .n-base-selection .n-base-selection__state-border) {
border: 1px solid #4ab9fd;
}
:deep(.n-tag) {
color: #fff;
background: #10273e00;
/* display:none; */
}
:deep(.n-tag .n-tag__border) {
border: none;
}
:deep(.n-base-selection-tag-wrapper) {
background: #10273e00;
}
/* zhaojunbao */
.top-toolbar {
position: absolute;
top: .5rem;
right: 0.5rem;
width: 240px;
height: 0.4rem;
color: #11e0ff;
z-index: 99999;
display: flex;
align-items: center;
justify-content: space-between;
.split-line {
width: 0.03rem;
height: 100%; height: 100%;
background: #11e0ff; overflow: hidden;
} }
.baojing {
position: relative; .cesium-container {
padding-left: 25px; width: 100%;
display: block; height: 100vh;
&::before { position: absolute;
content: ""; top: 0;
position: absolute; left: 0;
left: 0;
top: 50%;
transform: translateY(-50%);
width: 20px;
height: 20px;
background-image: url("@/assets/jinrun/baojing.png");
background-size: contain;
background-repeat: no-repeat;
}
}
.houtaiguanli {
position: relative;
padding-left: 25px;
display: block;
&::before {
content: "";
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
width: 20px;
height: 20px;
background-image: url("@/assets/jinrun/houtai.png");
background-size: contain;
background-repeat: no-repeat;
}
} }
}
#cesiumContainer {
.top,
.bottom,
.left,
.right {
position: absolute;
background-repeat: no-repeat;
}
.top {
top: 0;
width: 100%;
height: 1.25rem;
position: absolute;
.first-image {
width: 100%; width: 100%;
height: 100%; height: 100%;
position: relative;
.second-icon {
position: absolute;
top: 30%;
left: 50%;
transform: translate(-50%, -50%);
width: 5.04rem; /* 可根据实际需要调整大小 */
height: 0.54rem; /* 可根据实际需要调整大小 */
}
} }
}
.bottom { .personMessage {
bottom: 0; width: 450px;
left: 0; height: 250px;
width: 100%; position: absolute;
height: 0.4rem; padding: 15px 20px;
background-image: url("@/assets/jinrun/bottom.png"); color: white;
background-size: cover; font-family: sans-serif;
} font-size: 14px;
.left { pointer-events: auto;
top: 0rem; z-index: 9999;
left: 0; top: 100px;
width: 264px; left: 20%;
height: calc(100vh); background-image: url('@/assets/person2.png');
background-size: contain; background-size: 100% 100%;
background-position-x: left; transform: translate(50%, 50%);
background-image: url("@/assets/jinrun/left.png");
}
.right {
top: 0rem;
right: 0;
width: 264px;
height: calc(100vh);
background-image: url("@/assets/jinrun/right.png");
background-size: contain;
background-position-x: right;
}
.toggle-btn {
position: absolute;
top: 50%;
transform: translateY(-50%);
width: 0.71rem;
height: 1.87rem;
background-image: url("@/assets/jinrun/toggle-left.png");
background-size: cover;
background-repeat: no-repeat;
border-radius: 0 10px 10px 0;
cursor: pointer;
z-index: 100;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.3s ease;
&.left-toggle {
left: 5rem; /* 与左侧模块宽度一致 */
background-image: url("@/assets/jinrun/toggle-left.png");
} }
&.left-toggle:hover {
background-image: url("@/assets/jinrun/toggle-left_click.png"); .carMessage {
width: 600px;
height: 380px;
position: absolute;
padding: 15px 20px;
color: white;
font-family: sans-serif;
font-size: 14px;
pointer-events: auto;
z-index: 9999;
top: 100px;
left: 20%;
background-image: url('@/assets/person2.png');
background-size: 100% 100%;
transform: translate(50%, 50%);
} }
&.right-toggle { .equipmentMessage {
right: 5rem; /* 与左侧模块宽度一致 */ width: 450px;
background-image: url("@/assets/jinrun/toggle-right.png"); height: 290px;
position: absolute;
padding: 15px 20px;
color: white;
font-family: sans-serif;
font-size: 14px;
pointer-events: auto;
z-index: 9999;
top: 100px;
left: 20%;
background-image: url('@/assets/person2.png');
background-size: 100% 100%;
transform: translate(50%, 50%);
} }
&.right-toggle:hover {
background-image: url("@/assets/jinrun/toggle-right_click.png"); .videoMessage {
width: 680px;
height: 380px;
position: absolute;
padding: 15px 20px;
color: white;
font-family: sans-serif;
font-size: 14px;
pointer-events: auto;
z-index: 9999;
top: 100px;
left: 20%;
background-image: url('@/assets/person2.png');
background-size: 100% 100%;
transform: translate(50%, 50%);
} }
&.collapsed { .title1 {
&.left-toggle { margin-top: 5px;
left: 0.55rem; }
border-radius: 0 10px 10px 0;
.title2 {
color: #29d7fb;
margin-right: 10px;
}
.title3 {
display: flex;
align-items: center;
margin: 0px 0px 8px 0px;
}
.title4 {
color: #29d7fb;
margin-right: 10px;
margin-left: 20px;
}
span {
position: absolute;
z-index: 4;
left: 30px;
top: 10px;
}
.person1 {
width: 85%;
height: 40px;
background-image: url('@/assets/person1.png');
background-size: 100% 100%;
position: absolute;
left: 6px;
top: 20px;
}
.left-center {
width: 100%;
height: 10px;
border-bottom: 1px solid #147f9c;
}
.right {
width: 60%;
height: 50%;
/* margin-right: 20px; */
/* margin-top: 20px; */
}
#video {
height: 250px;
}
.video-top {
width: 100%;
height: 50%;
display: flex;
flex-direction: row;
flex-wrap: nowrap;
}
.video-bottom {
margin-right: 20px;
}
.select {
width: 100%;
border: none;
background-image: url('@/assets/multiple-pop.png');
}
.n-select {
background-image: url('@/assets/multiple-pop.png');
background-position: center;
}
.n-select .n-select-trigger {
background-color: transparent;
}
.n-select .n-select-menu {
background-color: transparent;
}
:deep(.n-base-selection .n-base-selection-tags) {
background-color: transparent !important;
}
:deep(.n-base-selection .n-base-selection-label .n-base-selection-input .n-base-selection-input__content) {
color: white !important;
}
:deep(.n-base-selection .n-base-selection__border, .n-base-selection .n-base-selection__state-border) {
border: 1px solid #4ab9fd;
}
:deep(.n-tag) {
color: #fff;
background: #10273e00;
/* display:none; */
}
:deep(.n-tag .n-tag__border) {
border: none;
}
:deep(.n-base-selection-tag-wrapper) {
background: #10273e00;
}
/* zhaojunbao */
.top-toolbar {
position: absolute;
top: 0.5rem;
right: 0.5rem;
width: 240px;
height: 0.4rem;
color: #11e0ff;
z-index: 99999;
display: flex;
align-items: center;
justify-content: space-between;
.split-line {
width: 0.03rem;
height: 100%;
background: #11e0ff;
} }
&.right-toggle { .baojing {
right: 0.55rem; position: relative;
border-radius: 10px 0 0 10px; padding-left: 25px;
display: block;
&::before {
content: '';
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
width: 20px;
height: 20px;
background-image: url('@/assets/jinrun/baojing.png');
background-size: contain;
background-repeat: no-repeat;
}
} }
}
.houtaiguanli {
.btn-arrow1 { position: relative;
img { padding-left: 25px;
width: 0.18rem; display: block;
&::before {
content: '';
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
width: 20px;
height: 20px;
background-image: url('@/assets/jinrun/houtai.png');
background-size: contain;
background-repeat: no-repeat;
}
} }
} }
.btn-arrow { .top,
width: 10px; .bottom,
height: 10px; .left,
border-top: 2px solid #fff; .right {
border-right: 2px solid #fff; position: absolute;
transition: transform 0.3s ease; background-repeat: no-repeat;
}
&::before {
content: ""; .top {
position: absolute; top: 0;
width: 2px; width: 100%;
height: 10px; height: 1.25rem;
background: #fff; position: absolute;
top: -4px;
right: 4px; .first-image {
width: 100%;
height: 100%;
position: relative;
& > img {
width: 100%;
}
.second-icon {
position: absolute;
top: 30%;
left: 50%;
transform: translate(-50%, -50%);
width: 5.04rem;
/* 可根据实际需要调整大小 */
height: 0.54rem;
/* 可根据实际需要调整大小 */
}
} }
} }
&.left-toggle .btn-arrow { .bottom {
transform: rotate(135deg); bottom: 0;
left: 0;
width: 100%;
height: 0.4rem;
background-image: url('@/assets/jinrun/bottom.png');
background-size: cover;
} }
&.right-toggle .btn-arrow { .left {
transform: rotate(-45deg); top: 0rem;
left: 0;
width: 5.76rem;
height: calc(100vh);
background-size: contain;
background-position-x: left;
background-image: url('@/assets/jinrun/bg-left.png');
} }
&.collapsed { .right {
top: 0rem;
right: 0;
width: 5.76rem;
height: calc(100vh);
background-image: url('@/assets/jinrun/bg-right.png');
background-size: contain;
background-position-x: right;
}
.toggle-btn {
position: absolute;
top: 50%;
transform: translateY(-50%);
width: 0.71rem;
height: 1.87rem;
background-image: url('@/assets/jinrun/toggle-left.png');
background-size: cover;
background-repeat: no-repeat;
border-radius: 0 10px 10px 0;
cursor: pointer;
z-index: 100;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.3s ease;
&.left-toggle {
left: 5rem;
/* 与左侧模块宽度一致 */
background-image: url('@/assets/jinrun/toggle-left.png');
}
&.left-toggle:hover {
background-image: url('@/assets/jinrun/toggle-left_click.png');
}
&.right-toggle {
right: 5rem;
/* 与左侧模块宽度一致 */
background-image: url('@/assets/jinrun/toggle-right.png');
}
&.right-toggle:hover {
background-image: url('@/assets/jinrun/toggle-right_click.png');
}
&.collapsed {
&.left-toggle {
left: 0.55rem;
border-radius: 0 10px 10px 0;
}
&.right-toggle {
right: 0.55rem;
border-radius: 10px 0 0 10px;
}
}
.btn-arrow1 {
img {
width: 0.18rem;
}
}
.btn-arrow {
width: 10px;
height: 10px;
border-top: 2px solid #fff;
border-right: 2px solid #fff;
transition: transform 0.3s ease;
&::before {
content: '';
position: absolute;
width: 2px;
height: 10px;
background: #fff;
top: -4px;
right: 4px;
}
}
&.left-toggle .btn-arrow { &.left-toggle .btn-arrow {
transform: rotate(-45deg); transform: rotate(135deg);
} }
&.right-toggle .btn-arrow { &.right-toggle .btn-arrow {
transform: rotate(135deg); transform: rotate(-45deg);
} }
&.collapsed {
&.left-toggle .btn-arrow {
transform: rotate(-45deg);
}
&.right-toggle .btn-arrow {
transform: rotate(135deg);
}
}
&:hover {
}
}
.slide-left-enter-active,
.slide-left-leave-active {
transition:
transform 0.5s ease,
opacity 0.5s ease;
}
.slide-left-enter-from {
transform: translateX(-100%);
opacity: 0;
}
.slide-left-leave-to {
transform: translateX(-100%);
opacity: 0;
}
.slide-right-enter-active,
.slide-right-leave-active {
transition:
transform 0.5s ease,
opacity 0.5s ease;
} }
&:hover { .slide-right-enter-from {
transform: translateX(100%);
opacity: 0;
}
.slide-right-leave-to {
transform: translateX(100%);
opacity: 0;
}
.left-modules:not(.v-enter-active):not(.v-leave-active).left-toggle:not(.collapsed) {
left: 0;
border-radius: 0 10px 10px 0;
}
.right-modules:not(.v-enter-active):not(.v-leave-active).right-toggle:not(.collapsed) {
right: 0;
border-radius: 10px 0 0 10px;
background: pink;
}
.left-modules,
.right-modules {
width: 4.6rem;
padding-top: 0.95rem;
position: absolute;
}
.left-modules {
left: 0;
margin-left: 0.4rem;
}
.right-modules {
right: 0;
margin-right: 0.4rem;
}
.arrow-font {
width: 20px;
color: #fff;
font-size: 0.18rem;
display: flex;
flex-direction: column;
}
.video-container {
width: 100%;
height: 250px;
border: 1px solid #ccc;
background: #f5f5f5;
position: relative;
}
#divPlugin {
width: 100%;
height: 100%;
}
.status-info {
position: absolute;
top: 10px;
right: 10px;
background: rgba(0, 0, 0, 0.7);
color: white;
padding: 5px 10px;
border-radius: 4px;
font-size: 12px;
} }
} </style>
.slide-left-enter-active, \ No newline at end of file
.slide-left-leave-active {
transition: transform 0.5s ease, opacity 0.5s ease;
}
.slide-left-enter-from {
transform: translateX(-100%);
opacity: 0;
}
.slide-left-leave-to {
transform: translateX(-100%);
opacity: 0;
}
.slide-right-enter-active,
.slide-right-leave-active {
transition: transform 0.5s ease, opacity 0.5s ease;
}
.slide-right-enter-from {
transform: translateX(100%);
opacity: 0;
}
.slide-right-leave-to {
transform: translateX(100%);
opacity: 0;
}
.left-modules:not(.v-enter-active):not(.v-leave-active).left-toggle:not(.collapsed) {
left: 0;
border-radius: 0 10px 10px 0;
}
.right-modules:not(.v-enter-active):not(.v-leave-active).right-toggle:not(.collapsed) {
right: 0;
border-radius: 10px 0 0 10px;
background: pink;
}
.left-modules,
.right-modules {
width: 4.6rem;
padding-top: .95rem;
position: absolute;
}
.left-modules {
left: 0;
margin-left: 0.4rem;
}
.right-modules {
right: 0;
margin-right: 0.4rem;
}
.arrow-font {
width: 20px;
color: #fff;
font-size: 0.18rem;
display: flex;
flex-direction: column;
}
</style>
<script setup lang="ts"> <script setup lang="ts">
import { onMounted, onUnmounted, ref, watch } from 'vue'; import { nextTick, onBeforeMount, onMounted, onUnmounted, ref, watch } from 'vue';
import '../../../../Cesium/Widgets/widgets.css'; import '../../../../Cesium/Widgets/widgets.css';
import { useMessage } from 'naive-ui'; import { useMessage } from 'naive-ui';
import { getCarPointAllCarApi, getFenceListsApi, getPointAllPersonApi } from '@/api'; import {
getCameraIdApi,
getCarPointAllCarApi,
getCemeraPointApi,
getFenceListsApi,
getHomeCarApi,
getMonitorIdApi,
getMonitorPointApi,
getPointAllPersonApi,
getPointListApi
} from '@/api';
import { create3D } from '@/api/utils/cesium'; import { create3D } from '@/api/utils/cesium';
import { getElevationFromRay, getElevationFromRays } from '@/api/utils/cesiumUtil'; import { getElevationFromRay, getElevationFromRays } from '@/api/utils/cesiumUtil';
import { cesiumToLongitudeAndLatitude } from '@/api/utils/coordinateUtil'; import { cesiumToLongitudeAndLatitude } from '@/api/utils/coordinateUtil';
import { getModel } from '@/api/utils/cesiumModel'; import { getModel } from '@/api/utils/cesiumModel';
import { iconPoint } from '@/api/utils/home/cesiumPositions'; import { iconPoint } from '@/api/utils/home/cesiumPositions';
import { carSpeed } from '@/api/utils/carSpeed';
import fullScreen from '@/utils/full'; import fullScreen from '@/utils/full';
import { webVideo } from '@/utils/ai';
import bluePersonIcon from '@/assets/blueperson.png'; import bluePersonIcon from '@/assets/blueperson.png';
import arrowLeftImg from '@/assets/jinrun/arrow-left.png'; import arrowLeftImg from '@/assets/jinrun/arrow-left.png';
import arrowRightImg from '@/assets/jinrun/arrow-right.png'; import arrowRightImg from '@/assets/jinrun/arrow-right.png';
import redCarIcon from '@/assets/icon15Red.png';
import redVideoIcon from '@/assets/icon16Red.png';
import redBianIcon from '@/assets/icon17Red.png';
import blueCarIcon from '@/assets/icon15.png';
import blueVideoIcon from '@/assets/icon16.png';
import blueBianIcon from '@/assets/icon17.png';
import redPersonIcon from '../../../assets/redperson.png'; import redPersonIcon from '../../../assets/redperson.png';
import MultiSelect from './appselect.vue'; import MultiSelect from './appselect.vue';
let viewer: any = null; let viewer: any = null;
const message = useMessage(); const message = useMessage();
let personEntity: any; let personEntity: any;
let pins: any = []; const pins: any = [];
const full = ref(false); const full = ref(false);
let entityId: any; let entityId: any;
let link: any;
let speed = 0;
let text = '';
const personList = ref([]); const personList = ref([]);
const modelData = ref([ const modelData = ref([
[122.04736846370741, 37.48958083145254], [122.04736846370741, 37.48958083145254],
...@@ -37,11 +58,11 @@ const options = [ ...@@ -37,11 +58,11 @@ const options = [
}, },
{ {
label: '在线监测设备', label: '在线监测设备',
value: '2' value: '3'
}, },
{ {
label: '视频监控', label: '视频监控',
value: '3' value: '2'
}, },
{ {
label: '人员定位', label: '人员定位',
...@@ -57,95 +78,8 @@ const options = [ ...@@ -57,95 +78,8 @@ const options = [
} }
]; ];
const value = ref(options.map(opt => opt.value)); const value = ref(options.map(opt => opt.value));
// 监听选中值的变化
watch(
value,
(newVal, oldVal) => {
// 防止无限递归
if (JSON.stringify(newVal) === JSON.stringify(oldVal)) return;
// 获取除全选外的所有选项值
const otherValues = options.slice(1).map(opt => opt.value);
// 检查是否选中了所有其他选项
const allOtherSelected = otherValues.every(val => newVal.includes(val));
// 检查是否点击了全选
const allSelectedNow = newVal.includes('1');
const allSelectedBefore = oldVal.includes('1');
// 点击了全选选项
if (allSelectedNow && !allSelectedBefore) {
value.value = options.map(opt => opt.value);
return;
}
// 取消了全选选项
if (!allSelectedNow && allSelectedBefore) {
// 检查是否所有其他选项都被选中
const allOtherOptionsSelected = otherValues.every(val => newVal.includes(val));
if (allOtherOptionsSelected) {
// 如果所有其他选项都被选中,取消所有选中状态
value.value = [];
} else {
// 如果不是所有其他选项都被选中,只取消全选选项
value.value = newVal.filter(val => val !== '1');
}
return;
}
const someOptionUnselected = oldVal.length > newVal.length;
if (someOptionUnselected && allSelectedNow) {
// 如果取消了某个选项且当前处于全选状态,取消全选,但保留其他选项
value.value = newVal.filter(val => val !== '1');
}
// 选中了所有其他选项,自动选中全选
if (allOtherSelected && !allSelectedNow) {
value.value = options.map(opt => opt.value);
}
// 如果取消了所有选项,清空value
if (newVal.length === 0) {
value.value = [];
}
},
{ deep: true }
);
// const data = ref([
// {
// type: 1,
// name: '仓房摄像头2',
// x: 122.04736846370741,
// y: 37.48958083145254
// },
// {
// type: 2,
// name: '边坡表面位移1',
// x: 122.04760069379522,
// y: 37.489226301608184
// },
// {
// type: 3,
// name: '车辆1',
// x: 122.04823299200363,
// y: 37.489451482540346
// },
// {
// type: 4,
// name: '人工1',
// x: 122.04802271634016,
// y: 37.48983410372907
// },
// {
// type: 5,
// name: '人工2',
// x: 122.04748237248322,
// y: 37.49016152294277
// }
// ]);
const data = ref([]); const data = ref([]);
const position = ref([]);
const heightData = ref([]);
const datasouce = ref(); const datasouce = ref();
const fence = ref<any>(); const fence = ref<any>();
const personShow = ref(false); const personShow = ref(false);
...@@ -160,8 +94,10 @@ const fenceData = ref({ ...@@ -160,8 +94,10 @@ const fenceData = ref({
imagePath: '', imagePath: '',
imageColor: '' imageColor: ''
}); });
const labelData = ref<any>();
const formData = ref([]); const formData = ref([]);
// zhaojunbao 开始 // zhaojunbao 开始
// REM自适应配置 // REM自适应配置
const active = ref(false); const active = ref(false);
...@@ -242,6 +178,57 @@ function add3dtiles() { ...@@ -242,6 +178,57 @@ function add3dtiles() {
}); });
} }
// 监听选中值的变化
watch(
value,
(newVal, oldVal) => {
// 防止无限递归
if (JSON.stringify(newVal) === JSON.stringify(oldVal)) return;
// 获取除全选外的所有选项值
const otherValues = options.slice(1).map(opt => opt.value);
// 检查是否选中了所有其他选项
const allOtherSelected = otherValues.every(val => newVal.includes(val));
// 检查是否点击了全选
const allSelectedNow = newVal.includes('1');
const allSelectedBefore = oldVal.includes('1');
// 点击了全选选项
if (allSelectedNow && !allSelectedBefore) {
value.value = options.map(opt => opt.value);
return;
}
// 取消了全选选项
if (!allSelectedNow && allSelectedBefore) {
// 检查是否所有其他选项都被选中
const allOtherOptionsSelected = otherValues.every(val => newVal.includes(val));
if (allOtherOptionsSelected) {
// 如果所有其他选项都被选中,取消所有选中状态
value.value = [];
} else {
// 如果不是所有其他选项都被选中,只取消全选选项
value.value = newVal.filter(val => val !== '1');
}
return;
}
const someOptionUnselected = oldVal.length > newVal.length;
if (someOptionUnselected && allSelectedNow) {
// 如果取消了某个选项且当前处于全选状态,取消全选,但保留其他选项
value.value = newVal.filter(val => val !== '1');
}
// 选中了所有其他选项,自动选中全选
if (allOtherSelected && !allSelectedNow) {
value.value = options.map(opt => opt.value);
}
// 如果取消了所有选项,清空value
if (newVal.length === 0) {
value.value = [];
}
},
{ deep: true }
);
// 监听选择框的变化 // 监听选择框的变化
watch( watch(
value, value,
...@@ -249,32 +236,45 @@ watch( ...@@ -249,32 +236,45 @@ watch(
// 如果选中了"全选",显示所有实体 // 如果选中了"全选",显示所有实体
if (newValue.includes('1')) { if (newValue.includes('1')) {
wallEntities.value.forEach(entity => (entity.show = true)); wallEntities.value.forEach(entity => (entity.show = true));
iconEntities.value.forEach(entity => (entity.show = true));
// 显示所有图标和标签
pins.forEach(pin => {
if (pin.entity) pin.entity.show = true;
if (pin.labelEntity) pin.labelEntity.show = true;
if (pin.backgroundEntity) pin.backgroundEntity.show = true;
});
} else { } else {
// 根据选中的选项显示对应实体 // 根据选中的选项显示对应实体
wallEntities.value.forEach(entity => { wallEntities.value.forEach(entity => {
entity.show = newValue.includes('6'); // 越界开采对应电子围栏 entity.show = newValue.includes('6'); // 越界开采对应电子围栏
}); });
iconEntities.value.forEach(entity => { // 根据选中的选项显示对应图标和标签
const type = entity.properties?.type?.getValue(); pins.forEach(pin => {
const type = pin.type;
let shouldShow = false;
switch (type) { switch (type) {
case 1: // 在线监测设备 case 1: // 人员定位
entity.show = newValue.includes('3'); shouldShow = newValue.includes('4');
break; break;
case 2: // 视频监控 case 2: // 车辆定位
entity.show = newValue.includes('2'); shouldShow = newValue.includes('5');
break; break;
case 3: // 车辆定位 case 3: // 在线监测设备
entity.show = newValue.includes('5'); shouldShow = newValue.includes('3');
break; break;
case 4: // 人员定位 case 4: // 视频监控
case 5: // 人员定位 shouldShow = newValue.includes('2');
entity.show = newValue.includes('4');
break; break;
default: default:
entity.show = false; shouldShow = false;
} }
// 设置图标和标签的显示状态
if (pin.entity) pin.entity.show = shouldShow;
if (pin.labelEntity) pin.labelEntity.show = shouldShow;
if (pin.backgroundEntity) pin.backgroundEntity.show = shouldShow;
}); });
} }
}, },
...@@ -327,9 +327,9 @@ function electronic(position: any, heightData: any, rangeType: any) { ...@@ -327,9 +327,9 @@ function electronic(position: any, heightData: any, rangeType: any) {
if (options && options.get) { if (options && options.get) {
let materail = let materail =
'czm_material czm_getMaterial(czm_materialInput materialInput)\n\ 'czm_material czm_getMaterial(czm_materialInput materialInput)\n\
{\n\ {\n\
czm_material material = czm_getDefaultMaterial(materialInput);\n\ czm_material material = czm_getDefaultMaterial(materialInput);\n\
vec2 st = materialInput.st;'; vec2 st = materialInput.st;';
if (options.freely == 'vertical') { if (options.freely == 'vertical') {
// (由下到上) // (由下到上)
materail += `vec4 colorImage = texture(image, vec2(fract(st.s), fract(float(${options.count})*st.t${ materail += `vec4 colorImage = texture(image, vec2(fract(st.s), fract(float(${options.count})*st.t${
...@@ -344,13 +344,13 @@ function electronic(position: any, heightData: any, rangeType: any) { ...@@ -344,13 +344,13 @@ function electronic(position: any, heightData: any, rangeType: any) {
// 泛光 // 泛光
materail += materail +=
'vec4 fragColor;\n\ 'vec4 fragColor;\n\
fragColor.rgb = (colorImage.rgb+color.rgb) / 1.0;\n\ fragColor.rgb = (colorImage.rgb+color.rgb) / 1.0;\n\
fragColor = czm_gammaCorrect(fragColor);\n\ fragColor = czm_gammaCorrect(fragColor);\n\
material.diffuse = colorImage.rgb;\n\ material.diffuse = colorImage.rgb;\n\
material.alpha = colorImage.a;\n\ material.alpha = colorImage.a;\n\
material.emission = fragColor.rgb;\n\ material.emission = fragColor.rgb;\n\
return material;\n\ return material;\n\
}'; }';
return materail; return materail;
} }
} }
...@@ -483,22 +483,41 @@ function electronic(position: any, heightData: any, rangeType: any) { ...@@ -483,22 +483,41 @@ function electronic(position: any, heightData: any, rangeType: any) {
function videosShow() { function videosShow() {
if (videoShow.value == true) { if (videoShow.value == true) {
videoShow.value = false; videoShow.value = false;
iconShow();
} }
} }
function equipmentsShow() { function equipmentsShow() {
if (equipmentShow.value == true) { if (equipmentShow.value == true) {
equipmentShow.value = false; equipmentShow.value = false;
iconShow();
} }
} }
function carsShow() { function carsShow() {
if (carShow.value == true) { if (carShow.value == true) {
carShow.value = false; carShow.value = false;
iconShow();
} }
} }
function personsShow() { function personsShow() {
if (personShow.value == true) { if (personShow.value == true) {
personShow.value = false; personShow.value = false;
iconShow();
}
}
function iconShow() {
for (const item of pins) {
if (item.type == 1) {
item.image = bluePersonIcon;
} else if (item.type == 2) {
item.image = blueCarIcon;
} else if (item.type == 3) {
item.image = blueBianIcon;
} else {
item.image = blueVideoIcon;
}
} }
iconPoint(viewer, pins);
} }
// 设置员工类型 // 设置员工类型
...@@ -513,103 +532,213 @@ function getPersonTypeName(type: number): string { ...@@ -513,103 +532,213 @@ function getPersonTypeName(type: number): string {
} }
} }
onMounted(() => { async function setTimePerson() {
const res = await getPointAllPersonApi();
for (const item of pins) {
const pin = res.data.data.find((personData: any) => personData.cardId == item.id);
if (pin) {
personShow.value = false;
item.image = bluePersonIcon;
item.position = {
lon: pin.lon,
lat: pin.lat
};
}
}
const carRes = await getCarPointAllCarApi();
for (const item of pins) {
const pin = carRes.data.data.find((carData: any) => carData.carNumber == item.id);
if (pin) {
carShow.value = false;
item.image = blueCarIcon;
item.position = {
lon: pin.lon,
lat: pin.lat
};
}
}
iconPoint(viewer, pins);
}
setInterval(setTimePerson, 2 * 60 * 1000);
onMounted(async () => {
add3dtiles(); add3dtiles();
setTimeout(async () => { setTimeout(async () => {
// electronic();
fenceListGet(); fenceListGet();
// 获取并显示人员数据
const res = await getPointAllPersonApi(); const res = await getPointAllPersonApi();
const personData = ref(res.data.data); const personData = res.data.data;
await iconPoint(viewer, personData, 'person_').then(result => { personData.map(item => {
pins = result; pins.push({
console.log('111', pins); id: item.cardId,
name: item.realName,
type: 1,
image: bluePersonIcon,
position: {
lon: item.lon,
lat: item.lat
},
data: item,
entity: null
});
}); });
// 获取并显示车辆数据,使用不同的前缀 // 获取并显示车辆数据,使用不同的前缀
const resCar = await getCarPointAllCarApi(); const resCar = await getCarPointAllCarApi();
const carData = ref(resCar.data.data); const carData = resCar.data.data;
await iconPoint(viewer, carData, 'car_').then(result => { carData.map(item => {
pins = [...pins, ...result]; pins.push({
console.log('222', pins); id: item.carNumber,
name: item.carNumber,
type: 2,
image: blueCarIcon,
position: {
lon: item.lon,
lat: item.lat
},
data: item,
entity: null
});
});
// 获取在线监测
const resPoint = await getMonitorPointApi();
const pointData = resPoint.data.data;
pointData.map(item => {
pins.push({
id: item.id,
type: 3,
name: item.equipname,
image: blueBianIcon,
position: {
lon: item.longitude,
lat: item.latitude
},
data: item,
entity: null,
label: null
});
});
// 获取视频监控信息
const resVideo = await getCemeraPointApi();
const videoData = resVideo.data.data;
videoData.map(item => {
pins.push({
id: item.id,
name: item.cameraName,
type: 4,
image: blueVideoIcon,
position: {
lon: item.lon,
lat: item.lat
},
data: item,
entity: null
});
}); });
// 保留原始数据引用用于其他操作 iconPoint(viewer, pins).then(result => {
data.value = [...res.data.data, ...resCar.data.data]; console.log(result);
});
}, 2000); }, 2000);
// setTimePerson();
// zhaojunbao 开始
// 初始化REM自适应
setRemUnit(); setRemUnit();
// 监听窗口大小变化 // 监听窗口大小变化
window.addEventListener('resize', setRemUnit); window.addEventListener('resize', setRemUnit);
// zhaojunbao 结束 // zhaojunbao 结束
let currentSelectedPerson = null;
const currentCar = ref<any>(null);
const handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas); const handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
// 鼠标点击事件
handler.setInputAction(function (click: any) { handler.setInputAction(async function (click: any) {
const pickedObject = viewer.scene.pick(click.position); const pickedObject = viewer.scene.pick(click.position);
entityId = pickedObject.id.id;
if (!pickedObject.collection) { for (const item of pins) {
videoShow.value = false; if (item.type == 1) {
equipmentShow.value = false; item.image = bluePersonIcon;
carShow.value = false; } else if (item.type == 2) {
personShow.value = false; item.image = blueCarIcon;
return; } else if (item.type == 3) {
item.image = blueBianIcon;
} else {
item.image = blueVideoIcon;
}
} }
if (Cesium.defined(pickedObject) && pickedObject.id) {
const pin = pins.find(p => p.entity === pickedObject.id); if (Cesium.defined(pickedObject) && Cesium.defined(pickedObject.id)) {
const pin = pins.find(item => item.entity === pickedObject.id);
if (pin.type == 1) { if (pin.type == 1) {
videoShow.value = true; equipmentShow.value = false;
videoShow.value = false;
carShow.value = false;
personShow.value = true;
labelData.value = pin.data;
pin.image = redPersonIcon;
} else if (pin.type == 2) { } else if (pin.type == 2) {
equipmentShow.value = true; // 车
} else if (pin.type == 3) { equipmentShow.value = false;
videoShow.value = false;
personShow.value = false;
carShow.value = true; carShow.value = true;
currentCar.value = pin.data; const res = await getHomeCarApi(pin.id);
} else { console.log(res);
personList.value = [];
if (typeof entityId === 'string' && entityId.startsWith('person_')) {
viewer.entities.values.forEach((entity: any) => {
if (typeof entity.id === 'string' && entity.id.startsWith('person_')) {
entity.billboard.image = bluePersonIcon;
}
});
const clickedEntity = viewer.entities.getById(entityId); if (res.data.code == 200) {
if (clickedEntity) { speed = res.data.data.point ? carSpeed(res.data.data) : 0;
clickedEntity.billboard.image = redPersonIcon; labelData.value = res.data.data;
currentSelectedPerson = clickedEntity; link = `${labelData.value.ipAddress}?lang=zh&devIdno=${labelData.value.cameraNo}&account=${labelData.value.username}&password=${labelData.value.password}&channel=1`;
} }
personShow.value = true; pin.image = redCarIcon;
if (pickedObject.id.personData) { } else if (pin.type == 3) {
personList.value.push({ // 监测设备
personId: pickedObject.id.personData.info.personId, videoShow.value = false;
realName: pickedObject.id.personData.info.realName, carShow.value = false;
remark: pickedObject.id.personData.info.remark, personShow.value = false;
phone: pickedObject.id.personData.info.phone, equipmentShow.value = true;
deptName: pickedObject.id.personData.info.deptName, const res = await getMonitorIdApi(pin.id);
personType: pickedObject.id.personData.info.personType if (res.data.code == 200) {
}); if (res.data.data.devicetype == 3) {
text = '表面位移';
} else if (res.data.data.devicetype == 6) {
text = '降雨量';
} }
} else { labelData.value = res.data.data;
personList.value = []; }
personShow.value = false;
if (personShow.value == false) { pin.image = redBianIcon;
const clickedEntity = viewer.entities.getById(entityId); } else {
clickedEntity.billboard.image = bluePersonIcon; // 摄像头
} equipmentShow.value = false;
videoShow.value = true;
carShow.value = false;
personShow.value = false;
videoShow.value = true;
const res = await getCameraIdApi(pin.id);
if (res.data.code == 200) {
labelData.value = res.data.data;
console.log(labelData.value);
const webRtcServrce = ref();
nextTick(() => {
webRtcServrce.value = new WebRtcStreamer('video', `${location.protocol}//` + `192.168.2.53:8000`);
webRtcServrce.value.connect(res.data.data.videoStream);
});
} }
pin.image = redVideoIcon;
} }
iconPoint(viewer, pins);
} else { } else {
videoShow.value = false;
equipmentShow.value = false; equipmentShow.value = false;
videoShow.value = false;
carShow.value = false; carShow.value = false;
personShow.value = false; personShow.value = false;
iconPoint(viewer, pins);
} }
}, Cesium.ScreenSpaceEventType.LEFT_CLICK); }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
}); });
...@@ -662,26 +791,26 @@ onUnmounted(() => { ...@@ -662,26 +791,26 @@ onUnmounted(() => {
&times; &times;
</button> </button>
</div> </div>
<div v-for="item in personList" style="line-height: 1.8"> <div style="line-height: 1.8">
<p class="title1"> <p class="title1">
<strong class="title2">姓名:</strong> <strong class="title2">姓名:</strong>
{{ item.realName }} {{ labelData.realName }}
</p> </p>
<p class="title1"> <p class="title1">
<strong class="title2">定位卡号:</strong> <strong class="title2">定位卡号:</strong>
{{ item.remark }} {{ labelData.cardId }}
</p> </p>
<p class="title1"> <p class="title1">
<strong class="title2">人员类型:</strong> <strong class="title2">人员类型:</strong>
{{ getPersonTypeName(item.personType) }} {{ getPersonTypeName(labelData.personType) }}
</p> </p>
<p class="title1"> <p class="title1">
<strong class="title2">电话:</strong> <strong class="title2">电话:</strong>
{{ item.phone }} {{ labelData.phone }}
</p> </p>
<p class="title1"> <p class="title1">
<strong class="title2">部门:</strong> <strong class="title2">部门:</strong>
{{ item.deptName }} {{ labelData.deptName }}
</p> </p>
</div> </div>
</div> </div>
...@@ -705,79 +834,54 @@ onUnmounted(() => { ...@@ -705,79 +834,54 @@ onUnmounted(() => {
<div class="left-top"> <div class="left-top">
<p class="title1"> <p class="title1">
<strong class="title2">车牌号:</strong> <strong class="title2">车牌号:</strong>
{{ currentCar?.carNumber || '暂无数据' }} {{ labelData.carNumber || '暂无数据' }}
</p> </p>
<p class="title1"> <p class="title1">
<strong class="title2">车队名称:</strong> <strong class="title2">车队名称:</strong>
{{ currentCar?.teamName || currentCar?.carName || '暂无数据' }} {{ labelData.teamName || '暂无数据' }}
</p> </p>
<p class="title1"> <p class="title1">
<strong class="title2">当前车速:</strong> <strong class="title2">当前车速:</strong>
{{ currentCar?.speed || 0 }}km/h {{ speed }} km/h
</p> </p>
<p class="title1"> <p class="title1">
<strong class="title2">车辆类型:</strong> <strong class="title2">车辆类型:</strong>
{{ currentCar?.carType || '暂无数据' }} {{ labelData.carType || '暂无数据' }}
</p> </p>
</div> </div>
<div class="left-center"></div> <div class="left-center"></div>
<div class="left-bottom"> <div class="left-bottom">
<p class="title1"> <p class="title1">
<strong class="title2">司机姓名:</strong> <strong class="title2">司机姓名:</strong>
{{ currentCar?.driverName || '暂无数据' }} {{ labelData.driverName || '暂无数据' }}
</p> </p>
<p class="title1"> <p class="title1">
<strong class="title2">工作开始时间:</strong> <strong class="title2">工作开始时间:</strong>
{{ currentCar?.workStartTime || '暂无数据' }} {{ labelData.workStartTime || '暂无数据' }}
</p> </p>
<p class="title1"> <p class="title1">
<strong class="title2">工作时长:</strong> <strong class="title2">工作时长:</strong>
{{ currentCar?.workDuration || '暂无数据' }} {{ labelData.workTime || '暂无数据' }}
</p> </p>
<p class="title1"> <p class="title1">
<strong class="title2">终端设备编号:</strong> <strong class="title2">终端设备编号:</strong>
{{ currentCar?.deviceNo || '暂无数据' }} {{ labelData.terminalNumber || '暂无数据' }}
</p> </p>
</div> </div>
</div> </div>
<div class="car-right"> <div class="car-right">
<!-- <iframe
<video id="video" controls autoplay muted playsinline width="100%" height="100%" allowfullscreen="true"
style="object-fit: fill; z-index: 1;"></video> allowtransparency="true"
--> allow="autoplay"
<div scrolling="no"
:style=" :src="link"
full width="100%"
? { height="100%"
border: '1px solid #ccc', frameborder="0"
padding: '2px', style="padding-right: 20px"
position: 'fixed', ></iframe>
top: 0, <!-- '${res.ipAddress}?lang=zh&devIdno=${res.cameraNo}&account=${res.username}&password=${res.password}&channel=1' -->
left: 0,
width: '100vw',
height: '100px',
zIndex: '99'
}
: {
padding: '2px',
height: '250px !important',
border: ' 1px solid #ccc',
position: 'relative',
margin: '0px 10px 0px 0px'
}
"
>
<div style="position: absolute; bottom: 5px; right: 5px; width: 40px; height: 40px; cursor: pointer">
<icon-gridicons-fullscreen-exit
v-if="full"
color="#11e0ff"
font-size="30"
@click="full = fullScreen(full)"
/>
<icon-gridicons-fullscreen v-else font-size="30" color="#11e0ff" @click="full = fullScreen(full)" />
</div>
<canvas id="canvas-4" style="width: 100%; height: 100%" width="800" height="600"></canvas>
</div>
</div> </div>
</div> </div>
</div> </div>
...@@ -799,27 +903,27 @@ onUnmounted(() => { ...@@ -799,27 +903,27 @@ onUnmounted(() => {
<div style="line-height: 1.8"> <div style="line-height: 1.8">
<p class="title1"> <p class="title1">
<strong class="title2">设备名称:</strong> <strong class="title2">设备名称:</strong>
设备表面位移01 {{ labelData.equipname }}
</p> </p>
<p class="title1"> <p class="title1">
<strong class="title2">设备状态:</strong> <strong class="title2">设备状态:</strong>
在线/离线 {{ labelData.dataStatus === 0 ? '在线' : '离线' }}
</p> </p>
<p class="title1"> <p class="title1">
<strong class="title2">设备类型:</strong> <strong class="title2">设备类型:</strong>
表面位移/降雨量/环境监测 {{ text }}
</p> </p>
<p class="title1"> <p class="title1">
<strong class="title2">监测值:</strong> <strong class="title2">监测值:</strong>
0.004mm {{ labelData.value }}
</p> </p>
<p class="title1"> <p class="title1">
<strong class="title2">监测时间:</strong> <strong class="title2">监测时间:</strong>
2025-10 10:10:10 {{ labelData.time }}
</p> </p>
<p class="title1"> <p class="title1">
<strong class="title2">数据状态:</strong> <strong class="title2">数据状态:</strong>
正常 {{ labelData.onlineStatus === 0 ? '正常' : '蓝色报警' }}
</p> </p>
</div> </div>
</div> </div>
...@@ -842,55 +946,28 @@ onUnmounted(() => { ...@@ -842,55 +946,28 @@ onUnmounted(() => {
<div class="video-top"> <div class="video-top">
<div class="title3"> <div class="title3">
<strong class="title2">● 摄像头名称:</strong> <strong class="title2">● 摄像头名称:</strong>
排土场入口 {{ labelData.areaName }}
</div> </div>
<div class="title3"> <div class="title3">
<strong class="title4">● 区域名称:</strong> <strong class="title4">● 区域名称:</strong>
排土场背部 {{ labelData.cameraName }}
</div> </div>
<div class="title3"> <div class="title3">
<strong class="title4">● 设备状态:</strong> <strong class="title4">● 设备状态:</strong>
在线/离线 {{ labelData.status === 0 ? '在线' : '离线' }}
</div> </div>
</div> </div>
<div class="video-bottom"> <div class="video-bottom">
<!-- <video
<NButton @click="login()">登陆</NButton> id="video"
<NButton @click="switchVideo()">切换视频流</NButton> controls
<div id="videoLayout" style="width: 500px; height: 250px; border: 1px solid red;"></div> autoplay
--> muted
<div playsinline
:style=" width="100%"
full height="100%"
? { style="object-fit: fill; z-index: 1"
border: '1px solid #ccc', ></video>
padding: '2px',
position: 'fixed',
top: 0,
left: 0,
width: '100vw',
height: '100px',
zIndex: '99'
}
: {
padding: '2px',
height: '250px !important',
border: ' 1px solid #ccc',
position: 'relative'
}
"
>
<div style="position: absolute; bottom: 5px; right: 5px; width: 40px; height: 40px; cursor: pointer">
<icon-gridicons-fullscreen-exit
v-if="full"
color="#11e0ff"
font-size="30"
@click="full = fullScreen(full)"
/>
<icon-gridicons-fullscreen v-else font-size="30" color="#11e0ff" @click="full = fullScreen(full)" />
</div>
<canvas id="canvas-4" style="width: 100%; height: 100%" width="800" height="600"></canvas>
</div>
</div> </div>
</div> </div>
</div> </div>
...@@ -908,8 +985,8 @@ onUnmounted(() => { ...@@ -908,8 +985,8 @@ onUnmounted(() => {
</div> </div>
</div> </div>
<div class="bottom"></div> <div class="bottom"></div>
<div class="left" v-show="isLeftModulesVisible"></div> <div v-show="isLeftModulesVisible" class="left"></div>
<div class="right" v-show="isRightModulesVisible"></div> <div v-show="isRightModulesVisible" class="right"></div>
<!-- 非cesium相关 开始 --> <!-- 非cesium相关 开始 -->
...@@ -919,11 +996,6 @@ onUnmounted(() => { ...@@ -919,11 +996,6 @@ onUnmounted(() => {
<div> <div>
<img :src="isLeftModulesVisible ? arrowLeftImg : arrowRightImg" alt="" srcset="" /> <img :src="isLeftModulesVisible ? arrowLeftImg : arrowRightImg" alt="" srcset="" />
<br /> <br />
<!--
<span class="arrow-font">{{ isLeftModulesVisible ? "" : "" }}</span>
<br />
<span class="arrow-font">{{ isLeftModulesVisible ? "" : "" }}</span>
-->
<div class="arrow-font"> <div class="arrow-font">
{{ isLeftModulesVisible ? '收起' : '展开' }} {{ isLeftModulesVisible ? '收起' : '展开' }}
</div> </div>
...@@ -938,11 +1010,6 @@ onUnmounted(() => { ...@@ -938,11 +1010,6 @@ onUnmounted(() => {
<div> <div>
<img :src="isLeftModulesVisible ? arrowRightImg : arrowLeftImg" alt="" srcset="" /> <img :src="isLeftModulesVisible ? arrowRightImg : arrowLeftImg" alt="" srcset="" />
<br /> <br />
<!--
<span class="arrow-font">{{ isLeftModulesVisible ? "" : "" }}</span>
<br />
<span class="arrow-font">{{ isLeftModulesVisible ? "" : "" }}</span>
-->
<div class="arrow-font"> <div class="arrow-font">
{{ isLeftModulesVisible ? '收起' : '展开' }} {{ isLeftModulesVisible ? '收起' : '展开' }}
</div> </div>
...@@ -952,7 +1019,7 @@ onUnmounted(() => { ...@@ -952,7 +1019,7 @@ onUnmounted(() => {
<!-- 左侧模块容器 --> <!-- 左侧模块容器 -->
<Transition name="slide-left"> <Transition name="slide-left">
<div class="left-modules" v-show="isLeftModulesVisible"> <div v-show="isLeftModulesVisible" class="left-modules">
<LeftDeviceStatus /> <LeftDeviceStatus />
<LeftRainfallTrend /> <LeftRainfallTrend />
<LeftOnlineMonitor /> <LeftOnlineMonitor />
...@@ -961,7 +1028,7 @@ onUnmounted(() => { ...@@ -961,7 +1028,7 @@ onUnmounted(() => {
<!-- 右侧模块容器 --> <!-- 右侧模块容器 -->
<Transition name="slide-right"> <Transition name="slide-right">
<div class="right-modules" v-show="isRightModulesVisible"> <div v-show="isRightModulesVisible" class="right-modules">
<RightAiWarning /> <RightAiWarning />
<RightEnvMonitor /> <RightEnvMonitor />
<RightTodayAlarm /> <RightTodayAlarm />
...@@ -977,6 +1044,7 @@ body { ...@@ -977,6 +1044,7 @@ body {
height: 100%; height: 100%;
overflow: hidden; overflow: hidden;
} }
.cesium-container { .cesium-container {
width: 100%; width: 100%;
height: 100vh; height: 100vh;
...@@ -1001,7 +1069,7 @@ body { ...@@ -1001,7 +1069,7 @@ body {
pointer-events: auto; pointer-events: auto;
z-index: 9999; z-index: 9999;
top: 100px; top: 100px;
left: 30%; left: 20%;
background-image: url('@/assets/person2.png'); background-image: url('@/assets/person2.png');
background-size: 100% 100%; background-size: 100% 100%;
transform: translate(50%, 50%); transform: translate(50%, 50%);
...@@ -1018,7 +1086,7 @@ body { ...@@ -1018,7 +1086,7 @@ body {
pointer-events: auto; pointer-events: auto;
z-index: 9999; z-index: 9999;
top: 100px; top: 100px;
left: 30%; left: 20%;
background-image: url('@/assets/person2.png'); background-image: url('@/assets/person2.png');
background-size: 100% 100%; background-size: 100% 100%;
transform: translate(50%, 50%); transform: translate(50%, 50%);
...@@ -1035,7 +1103,7 @@ body { ...@@ -1035,7 +1103,7 @@ body {
pointer-events: auto; pointer-events: auto;
z-index: 9999; z-index: 9999;
top: 100px; top: 100px;
left: 30%; left: 20%;
background-image: url('@/assets/person2.png'); background-image: url('@/assets/person2.png');
background-size: 100% 100%; background-size: 100% 100%;
transform: translate(50%, 50%); transform: translate(50%, 50%);
...@@ -1052,7 +1120,7 @@ body { ...@@ -1052,7 +1120,7 @@ body {
pointer-events: auto; pointer-events: auto;
z-index: 9999; z-index: 9999;
top: 100px; top: 100px;
left: 30%; left: 20%;
background-image: url('@/assets/person2.png'); background-image: url('@/assets/person2.png');
background-size: 100% 100%; background-size: 100% 100%;
transform: translate(50%, 50%); transform: translate(50%, 50%);
...@@ -1070,7 +1138,7 @@ body { ...@@ -1070,7 +1138,7 @@ body {
.title3 { .title3 {
display: flex; display: flex;
align-items: center; align-items: center;
margin: 0px 0px 8px 10px; margin: 0px 0px 8px 0px;
} }
.title4 { .title4 {
...@@ -1109,6 +1177,10 @@ span { ...@@ -1109,6 +1177,10 @@ span {
/* margin-top: 20px; */ /* margin-top: 20px; */
} }
#video {
height: 250px;
}
.video-top { .video-top {
width: 100%; width: 100%;
height: 50%; height: 50%;
...@@ -1161,6 +1233,7 @@ span { ...@@ -1161,6 +1233,7 @@ span {
:deep(.n-tag .n-tag__border) { :deep(.n-tag .n-tag__border) {
border: none; border: none;
} }
:deep(.n-base-selection-tag-wrapper) { :deep(.n-base-selection-tag-wrapper) {
background: #10273e00; background: #10273e00;
} }
...@@ -1177,15 +1250,18 @@ span { ...@@ -1177,15 +1250,18 @@ span {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
.split-line { .split-line {
width: 0.03rem; width: 0.03rem;
height: 100%; height: 100%;
background: #11e0ff; background: #11e0ff;
} }
.baojing { .baojing {
position: relative; position: relative;
padding-left: 25px; padding-left: 25px;
display: block; display: block;
&::before { &::before {
content: ''; content: '';
position: absolute; position: absolute;
...@@ -1199,10 +1275,12 @@ span { ...@@ -1199,10 +1275,12 @@ span {
background-repeat: no-repeat; background-repeat: no-repeat;
} }
} }
.houtaiguanli { .houtaiguanli {
position: relative; position: relative;
padding-left: 25px; padding-left: 25px;
display: block; display: block;
&::before { &::before {
content: ''; content: '';
position: absolute; position: absolute;
...@@ -1225,6 +1303,7 @@ span { ...@@ -1225,6 +1303,7 @@ span {
position: absolute; position: absolute;
background-repeat: no-repeat; background-repeat: no-repeat;
} }
.top { .top {
top: 0; top: 0;
width: 100%; width: 100%;
...@@ -1235,7 +1314,8 @@ span { ...@@ -1235,7 +1314,8 @@ span {
width: 100%; width: 100%;
height: 100%; height: 100%;
position: relative; position: relative;
&>img{
& > img {
width: 100%; width: 100%;
} }
...@@ -1244,11 +1324,14 @@ span { ...@@ -1244,11 +1324,14 @@ span {
top: 30%; top: 30%;
left: 50%; left: 50%;
transform: translate(-50%, -50%); transform: translate(-50%, -50%);
width: 5.04rem; /* 可根据实际需要调整大小 */ width: 5.04rem;
height: 0.54rem; /* 可根据实际需要调整大小 */ /* 可根据实际需要调整大小 */
height: 0.54rem;
/* 可根据实际需要调整大小 */
} }
} }
} }
.bottom { .bottom {
bottom: 0; bottom: 0;
left: 0; left: 0;
...@@ -1257,6 +1340,7 @@ span { ...@@ -1257,6 +1340,7 @@ span {
background-image: url('@/assets/jinrun/bottom.png'); background-image: url('@/assets/jinrun/bottom.png');
background-size: cover; background-size: cover;
} }
.left { .left {
top: 0rem; top: 0rem;
left: 0; left: 0;
...@@ -1266,6 +1350,7 @@ span { ...@@ -1266,6 +1350,7 @@ span {
background-position-x: left; background-position-x: left;
background-image: url('@/assets/jinrun/bg-left.png'); background-image: url('@/assets/jinrun/bg-left.png');
} }
.right { .right {
top: 0rem; top: 0rem;
right: 0; right: 0;
...@@ -1294,17 +1379,21 @@ span { ...@@ -1294,17 +1379,21 @@ span {
transition: all 0.3s ease; transition: all 0.3s ease;
&.left-toggle { &.left-toggle {
left: 5rem; /* 与左侧模块宽度一致 */ left: 5rem;
/* 与左侧模块宽度一致 */
background-image: url('@/assets/jinrun/toggle-left.png'); background-image: url('@/assets/jinrun/toggle-left.png');
} }
&.left-toggle:hover { &.left-toggle:hover {
background-image: url('@/assets/jinrun/toggle-left_click.png'); background-image: url('@/assets/jinrun/toggle-left_click.png');
} }
&.right-toggle { &.right-toggle {
right: 5rem; /* 与左侧模块宽度一致 */ right: 5rem;
/* 与左侧模块宽度一致 */
background-image: url('@/assets/jinrun/toggle-right.png'); background-image: url('@/assets/jinrun/toggle-right.png');
} }
&.right-toggle:hover { &.right-toggle:hover {
background-image: url('@/assets/jinrun/toggle-right_click.png'); background-image: url('@/assets/jinrun/toggle-right_click.png');
} }
...@@ -1423,6 +1512,7 @@ span { ...@@ -1423,6 +1512,7 @@ span {
left: 0; left: 0;
margin-left: 0.4rem; margin-left: 0.4rem;
} }
.right-modules { .right-modules {
right: 0; right: 0;
margin-right: 0.4rem; margin-right: 0.4rem;
...@@ -1435,4 +1525,28 @@ span { ...@@ -1435,4 +1525,28 @@ span {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
} }
.video-container {
width: 100%;
height: 250px;
border: 1px solid #ccc;
background: #f5f5f5;
position: relative;
}
#divPlugin {
width: 100%;
height: 100%;
}
.status-info {
position: absolute;
top: 10px;
right: 10px;
background: rgba(0, 0, 0, 0.7);
color: white;
padding: 5px 10px;
border-radius: 4px;
font-size: 12px;
}
</style> </style>
...@@ -55,9 +55,9 @@ const bgColor = computed(() => { ...@@ -55,9 +55,9 @@ const bgColor = computed(() => {
<!-- <WaveBg class="box" /> --> <!-- <WaveBg class="box" /> -->
<NCard :bordered="false" class="relative z-4 w-auto rd-12px"> <NCard :bordered="false" class="relative z-4 w-auto rd-12px">
<div class="w-400px lt-sm:w-300px"> <div class="w-400px lt-sm:w-300px">
<header class="flex-y-center justify-between"> <header class="flex-x-center justify-between" style="display: flex;justify-content: center;">
<!-- <SystemLogo class="text-64px text-primary lt-sm:text-48px" /> --> <!-- <SystemLogo class="text-64px text-primary lt-sm:text-48px" /> -->
<h3 class="text-28px text-primary font-600 lt-sm:text-22px">{{ $t('system.title') }}</h3> <h3 class="text-28px text-primary font-600 lt-sm:text-22px form-t">{{ $t('system.title') }}</h3>
<div class="i-flex-col"> <div class="i-flex-col">
<!-- <ThemeSchemaSwitch <!-- <ThemeSchemaSwitch
:theme-schema="themeStore.themeScheme" :theme-schema="themeStore.themeScheme"
...@@ -65,17 +65,17 @@ const bgColor = computed(() => { ...@@ -65,17 +65,17 @@ const bgColor = computed(() => {
class="text-20px lt-sm:text-18px" class="text-20px lt-sm:text-18px"
@switch="themeStore.toggleThemeScheme" @switch="themeStore.toggleThemeScheme"
/> --> /> -->
<LangSwitch <!-- <LangSwitch
v-if="themeStore.header.multilingual.visible" v-if="themeStore.header.multilingual.visible"
:lang="appStore.locale" :lang="appStore.locale"
:lang-options="appStore.localeOptions" :lang-options="appStore.localeOptions"
:show-tooltip="false" :show-tooltip="false"
@change-lang="appStore.changeLocale" @change-lang="appStore.changeLocale"
/> /> -->
</div> </div>
</header> </header>
<main class="pt-24px"> <main class="pt-24px">
<h3 class="text-18px text-primary font-medium">{{ $t(activeModule.label) }}</h3> <h3 class="text-18px text-primary font-medium">账号登录</h3>
<div class="pt-24px"> <div class="pt-24px">
<Transition :name="themeStore.page.animateMode" mode="out-in" appear> <Transition :name="themeStore.page.animateMode" mode="out-in" appear>
<component :is="activeModule.component" /> <component :is="activeModule.component" />
......
<template>
<div class="captcha-container">
<canvas ref="canvasRef" @click="refreshCaptcha" width="120" height="39"></canvas>
</div>
</template>
<script lang="ts" setup>
import { ref, onMounted } from 'vue';
const canvasRef = ref(null);
const captchaText = ref('');
// 生成随机数字(默认4位)
const generateRandomDigits = (length = 4) => {
return Array.from({ length }, () => Math.floor(Math.random() * 10)).join('');
};
// 绘制验证码
const drawCaptcha = () => {
const canvas = canvasRef.value;
if (!canvas) return;
const ctx = canvas.getContext('2d');
ctx.clearRect(0, 0, canvas.width, canvas.height);
// 生成新验证码
captchaText.value = generateRandomDigits();
// 背景色
ctx.fillStyle = '#f5f5f5';
ctx.fillRect(0, 0, canvas.width, canvas.height);
// 绘制文字(随机位置、颜色、旋转)
for (let i = 0; i < captchaText.value.length; i++) {
ctx.font = 'bold 24px Arial';
ctx.fillStyle = getRandomColor();
ctx.save();
ctx.translate(10 + i * 30, 28);
ctx.rotate((Math.random() - 0.5) * 0.4);
ctx.fillText(captchaText.value[i], 0, 0);
ctx.restore();
}
// 绘制干扰线
for (let i = 0; i < 15; i++) {
ctx.strokeStyle = getRandomColor(300);
ctx.beginPath();
ctx.moveTo(
Math.random() * canvas.width,
Math.random() * canvas.height
);
ctx.lineTo(
Math.random() * canvas.width,
Math.random() * canvas.height
);
ctx.stroke();
}
};
// 随机颜色
const getRandomColor = (min = 50) => {
const r = min + Math.floor(Math.random() * (100 - min));
const g = min + Math.floor(Math.random() * (100 - min));
const b = min + Math.floor(Math.random() * (100 - min));
return `rgb(${r}, ${g}, ${b})`;
};
// 点击刷新
const refreshCaptcha = () => {
drawCaptcha();
};
// 初始化
onMounted(() => {
drawCaptcha();
});
// 暴露验证码文本(供父组件校验)
defineExpose({
captchaText,
});
</script>
<style scoped>
.captcha-container {
display: inline-block;
cursor: pointer;
}
canvas {
border: 1px solid #ddd;
border-radius: 4px;
}
.hint {
font-size: 12px;
color: #999;
text-align: center;
}
</style>
\ No newline at end of file
...@@ -6,9 +6,14 @@ import { api_loginPost } from '@/api'; ...@@ -6,9 +6,14 @@ import { api_loginPost } from '@/api';
import { useAuthStore } from '@/store/modules/auth'; import { useAuthStore } from '@/store/modules/auth';
import { useRouterPush } from '@/hooks/common/router'; import { useRouterPush } from '@/hooks/common/router';
import { useFormRules, useNaiveForm } from '@/hooks/common/form'; import { useFormRules, useNaiveForm } from '@/hooks/common/form';
import Captcha from '../modules/Captcha.vue';
import { localStg } from '@/utils/storage'; import { localStg } from '@/utils/storage';
import { $t } from '@/locales'; import { $t } from '@/locales';
import { useMessage } from 'naive-ui'; import { useMessage } from 'naive-ui';
import { loginRules } from '@/rules/rules';
import { User } from '@vicons/fa';
import { IosLock } from '@vicons/ionicons4';
import { ShieldTask16Filled } from '@vicons/fluent'
defineOptions({ defineOptions({
name: 'PwdLogin' name: 'PwdLogin'
...@@ -21,21 +26,13 @@ const { formRef, validate } = useNaiveForm(); ...@@ -21,21 +26,13 @@ const { formRef, validate } = useNaiveForm();
interface FormModel { interface FormModel {
username: string; username: string;
password: string; password: string;
yzmcode: string;
} }
const model: FormModel = reactive({ const model: FormModel = reactive({
username: 'admin', username: '',
password: 'admin123' password: '',
}); yzmcode:''
const rules = computed<Record<keyof FormModel, App.Global.FormRule[]>>(() => {
const { formRules } = useFormRules();
return {
username: formRules.username,
password: formRules.pwd
};
}); });
async function handleSubmit() { async function handleSubmit() {
...@@ -61,12 +58,10 @@ async function handleSubmit() { ...@@ -61,12 +58,10 @@ async function handleSubmit() {
} }
</script> </script>
<template> <template>
<NForm ref="formRef" :model="model" :rules="rules" size="large" :show-label="false" @keyup.enter="handleSubmit"> <NForm ref="formRef" :model="model" :rules="loginRules" size="large" :show-label="false" @keyup.enter="handleSubmit">
<NFormItem path="username"> <NFormItem path="username">
<NInput v-model:value="model.username" :placeholder="$t('page.login.common.userNamePlaceholder')" /> <NInput v-model:value="model.username" :placeholder="$t('page.login.common.userNamePlaceholder')" />
</NFormItem> </NFormItem>
...@@ -78,6 +73,22 @@ async function handleSubmit() { ...@@ -78,6 +73,22 @@ async function handleSubmit() {
:placeholder="$t('page.login.common.passwordPlaceholder')" :placeholder="$t('page.login.common.passwordPlaceholder')"
/> />
</NFormItem> </NFormItem>
<NFormItem path="yzmcode">
<n-row>
<n-col :span = "16">
<NInput class="itemCode" v-model:value="model.yzmcode" show-password-on="click"
:placeholder="'请输入验证码'">
</NInput>
</n-col>
<n-col :span = "6">
<div style="margin-left: 10px;">
<Captcha ref="captchaRef" />
</div>
</n-col>
</n-row>
</NFormItem>
<NSpace vertical :size="24"> <NSpace vertical :size="24">
<NButton type="primary" size="large" round block :loading="authStore.loginLoading" @click="handleSubmit"> <NButton type="primary" size="large" round block :loading="authStore.loginLoading" @click="handleSubmit">
{{ $t('common.confirm') }} {{ $t('common.confirm') }}
......
...@@ -13,7 +13,7 @@ onMounted(async () => { ...@@ -13,7 +13,7 @@ onMounted(async () => {
</script> </script>
<template> <template>
<iframe src="http://192.168.2.54:9528/large" frameborder="0"></iframe> <iframe allowfullscreen="true" allowtransparency="true" allow="autoplay" scrolling="no" src="http://192.168.2.54:9528/large" frameborder="0"></iframe>
</template> </template>
<style scoped></style> <style scoped></style>
\ No newline at end of file
...@@ -13,7 +13,7 @@ onMounted(async () => { ...@@ -13,7 +13,7 @@ onMounted(async () => {
</script> </script>
<template> <template>
<iframe src="http://192.168.2.54:9528/camera" frameborder="0"></iframe> <iframe allowfullscreen="true" allowtransparency="true" allow="autoplay" scrolling="no" src="http://192.168.2.54:9528/camera" frameborder="0"></iframe>
</template> </template>
<style scoped></style> <style scoped></style>
...@@ -197,8 +197,10 @@ const treeData = ref<any>([]) ...@@ -197,8 +197,10 @@ const treeData = ref<any>([])
watch(posArr.value, async (val, old) => { watch(posArr.value, async (val, old) => {
if (!formData.value.rangeType) { if (!formData.value.rangeType) {
message.info('请先选取围栏类型后在进行操作') if(!showModal) {
return message.info('请先选取围栏类型后在进行操作')
return
}
} }
if (pins.length > 0) { if (pins.length > 0) {
handlerClean(); handlerClean();
......
<template> <template>
<div>表面位移</div> <iframe style="width: 100%; height: 100%;" src="http://192.168.2.15:84/dataMonitor/bmwy/history" frameborder="0"></iframe>
</template> </template>
<script lang="ts" setup></script> <script lang="ts" setup>
import { api_tokenGet } from '@/api';
import { useMessage } from 'naive-ui';
import { onMounted } from 'vue';
<style scoped> onMounted(async () => {
</style> const message = useMessage();
\ No newline at end of file let res = await api_tokenGet()
if (res.data.code == 401) {
message.error('登录过期');
}
})
</script>
<style scoped></style>
\ No newline at end of file
<template> <template>
<div>降雨量</div> <iframe style="width: 100%; height: 100%;" src="http://192.168.2.15:84/dataMonitor/jyl/history" frameborder="0"></iframe>
</template> </template>
<script lang="ts" setup></script> <script lang="ts" setup>
import { api_tokenGet } from '@/api';
import { useMessage } from 'naive-ui';
import { onMounted } from 'vue';
<style scoped> onMounted(async () => {
</style> const message = useMessage();
\ No newline at end of file let res = await api_tokenGet()
if (res.data.code == 401) {
message.error('登录过期');
}
})
</script>
<style scoped></style>
\ No newline at end of file
<template> <template>
<div>可视化大屏</div> <iframe style="width: 100%; height: 100%;" src="http://192.168.2.15:84/index" frameborder="0"></iframe>
</template> </template>
<script lang="ts" setup></script> <script lang="ts" setup>
import { api_tokenGet } from '@/api';
import { useMessage } from 'naive-ui';
import { onMounted } from 'vue';
<style scoped> onMounted(async () => {
</style> const message = useMessage();
\ No newline at end of file let res = await api_tokenGet()
if (res.data.code == 401) {
message.error('登录过期');
}
})
</script>
<style scoped></style>
\ No newline at end of file
<template> <template>
<div>监测值录入</div> <iframe style="width: 100%; height: 100%;" src="http://192.168.2.15:84/personMonitor/valueInput" frameborder="0"></iframe>
</template> </template>
<script lang="ts" setup></script> <script lang="ts" setup>
import { api_tokenGet } from '@/api';
import { useMessage } from 'naive-ui';
import { onMounted } from 'vue';
<style scoped> onMounted(async () => {
</style> const message = useMessage();
\ No newline at end of file let res = await api_tokenGet()
if (res.data.code == 401) {
message.error('登录过期');
}
})
</script>
<style scoped></style>
\ No newline at end of file
<template> <template>
<div>监测点管理</div> <iframe style="width: 100%; height: 100%;" src="http://192.168.2.15:84/personMonitor/monitorPoints" frameborder="0"></iframe>
</template> </template>
<script lang="ts" setup></script> <script lang="ts" setup>
import { api_tokenGet } from '@/api';
import { useMessage } from 'naive-ui';
import { onMounted } from 'vue';
<style scoped> onMounted(async () => {
</style> const message = useMessage();
\ No newline at end of file let res = await api_tokenGet()
if (res.data.code == 401) {
message.error('登录过期');
}
})
</script>
<style scoped></style>
\ No newline at end of file
<template> <template>
<div>报警列表</div> <iframe style="width: 100%; height: 100%;" src="http://192.168.2.15:84/alarmManage/history" frameborder="0"></iframe>
</template> </template>
<script lang="ts" setup></script> <script lang="ts" setup>
import { api_tokenGet } from '@/api';
import { useMessage } from 'naive-ui';
import { onMounted } from 'vue';
<style scoped> onMounted(async () => {
</style> const message = useMessage();
\ No newline at end of file let res = await api_tokenGet()
if (res.data.code == 401) {
message.error('登录过期');
}
})
</script>
<style scoped></style>
\ No newline at end of file
<template> <template>
<div>预警值设置</div> <iframe style="width: 100%; height: 100%;" src="http://192.168.2.15:84/alarmManage/warning" frameborder="0"></iframe>
</template> </template>
<script lang="ts" setup></script> <script lang="ts" setup>
import { api_tokenGet } from '@/api';
import { useMessage } from 'naive-ui';
import { onMounted } from 'vue';
<style scoped> onMounted(async () => {
</style> const message = useMessage();
\ No newline at end of file let res = await api_tokenGet()
if (res.data.code == 401) {
message.error('登录过期');
}
})
</script>
<style scoped></style>
\ No newline at end of file
<template> <template>
<div>检查项管理</div> <iframe style="width: 100%; height: 100%;" src="http://192.168.2.15:84/personInspection/checkItem" frameborder="0"></iframe>
</template> </template>
<script lang="ts" setup></script> <script lang="ts" setup>
import { api_tokenGet } from '@/api';
import { useMessage } from 'naive-ui';
import { onMounted } from 'vue';
<style scoped> onMounted(async () => {
</style> const message = useMessage();
\ No newline at end of file let res = await api_tokenGet()
if (res.data.code == 401) {
message.error('登录过期');
}
})
</script>
<style scoped></style>
\ No newline at end of file
<template> <template>
<div>检查结果录入</div> <iframe style="width: 100%; height: 100%;" src="http://192.168.2.15:84/personInspection/checkResult" frameborder="0"></iframe>
</template> </template>
<script lang="ts" setup></script> <script lang="ts" setup>
import { api_tokenGet } from '@/api';
import { useMessage } from 'naive-ui';
import { onMounted } from 'vue';
<style scoped> onMounted(async () => {
</style> const message = useMessage();
\ No newline at end of file let res = await api_tokenGet()
if (res.data.code == 401) {
message.error('登录过期');
}
})
</script>
<style scoped></style>
\ No newline at end of file
<template> <template>
<div>检查项类型管理</div> <iframe style="width: 100%; height: 100%;" src="http://192.168.2.15:84/personInspection/checkMode" frameborder="0"></iframe>
</template> </template>
<script lang="ts" setup></script> <script lang="ts" setup>
import { api_tokenGet } from '@/api';
import { useMessage } from 'naive-ui';
import { onMounted } from 'vue';
<style scoped> onMounted(async () => {
</style> const message = useMessage();
\ No newline at end of file let res = await api_tokenGet()
if (res.data.code == 401) {
message.error('登录过期');
}
})
</script>
<style scoped></style>
\ No newline at end of file
<template> <template>
<div>设备管理</div> <iframe style="width: 100%; height: 100%;" src="http://192.168.2.15:84/system/deviceManage" frameborder="0"></iframe>
</template> </template>
<script lang="ts" setup></script> <script lang="ts" setup>
import { api_tokenGet } from '@/api';
import { useMessage } from 'naive-ui';
import { onMounted } from 'vue';
<style scoped> onMounted(async () => {
</style> const message = useMessage();
\ No newline at end of file let res = await api_tokenGet()
if (res.data.code == 401) {
message.error('登录过期');
}
})
</script>
<style scoped></style>
\ No newline at end of file
<template> <template>
<div>首页模块管理</div> <iframe style="width: 100%; height: 100%;" src="http://192.168.2.15:84/system/monitorItems" frameborder="0"></iframe>
</template> </template>
<script lang="ts" setup></script> <script lang="ts" setup>
import { api_tokenGet } from '@/api';
import { useMessage } from 'naive-ui';
import { onMounted } from 'vue';
<style scoped> onMounted(async () => {
</style> const message = useMessage();
\ No newline at end of file let res = await api_tokenGet()
if (res.data.code == 401) {
message.error('登录过期');
}
})
</script>
<style scoped></style>
\ No newline at end of file
<template> <template>
<div>模块化数据配置</div> <iframe style="width: 100%; height: 100%;" src="http://192.168.2.15:84/system/moduleConfig" frameborder="0"></iframe>
</template> </template>
<script lang="ts" setup></script> <script lang="ts" setup>
import { api_tokenGet } from '@/api';
import { useMessage } from 'naive-ui';
import { onMounted } from 'vue';
<style scoped> onMounted(async () => {
</style> const message = useMessage();
\ No newline at end of file let res = await api_tokenGet()
if (res.data.code == 401) {
message.error('登录过期');
}
})
</script>
<style scoped></style>
\ No newline at end of file
<template> <template>
<div>监测点配置</div> <iframe style="width: 100%; height: 100%;" src="http://192.168.2.15:84/system/monitorPointConfig" frameborder="0"></iframe>
</template> </template>
<script lang="ts" setup></script> <script lang="ts" setup>
import { api_tokenGet } from '@/api';
import { useMessage } from 'naive-ui';
import { onMounted } from 'vue';
<style scoped> onMounted(async () => {
</style> const message = useMessage();
\ No newline at end of file let res = await api_tokenGet()
if (res.data.code == 401) {
message.error('登录过期');
}
})
</script>
<style scoped></style>
\ No newline at end of file
...@@ -145,7 +145,6 @@ function selectChange(item:any) { ...@@ -145,7 +145,6 @@ function selectChange(item:any) {
} }
function handleSearch() { function handleSearch() {
console.log(personValue.value);
if(personValue.value == '') { if(personValue.value == '') {
message.info('请选择您要查询的人员'); message.info('请选择您要查询的人员');
return; return;
...@@ -162,6 +161,7 @@ function handleReset() { ...@@ -162,6 +161,7 @@ function handleReset() {
entity.billboard.image = bluePersonIcon; entity.billboard.image = bluePersonIcon;
} }
}); });
value.value = null;
personList.value = []; personList.value = [];
personShow.value = false; personShow.value = false;
message.success('重置成功'); message.success('重置成功');
...@@ -240,6 +240,7 @@ onMounted(() => { ...@@ -240,6 +240,7 @@ onMounted(() => {
phone: pickedObject.id.personData.info.phone, phone: pickedObject.id.personData.info.phone,
deptName: pickedObject.id.personData.info.deptName, deptName: pickedObject.id.personData.info.deptName,
personType: pickedObject.id.personData.info.personType, personType: pickedObject.id.personData.info.personType,
cardId: pickedObject.id.personData.info.cardId,
}) })
} }
...@@ -292,7 +293,7 @@ onMounted(() => { ...@@ -292,7 +293,7 @@ onMounted(() => {
</div> </div>
<div style="line-height: 1.8;" v-for="item in personList"> <div style="line-height: 1.8;" v-for="item in personList">
<p class="title1"><strong class="title2">姓名:</strong> {{ item.realName }}</p> <p class="title1"><strong class="title2">姓名:</strong> {{ item.realName }}</p>
<p class="title1"><strong class="title2">定位卡号:</strong> {{ item.remark }}</p> <p class="title1"><strong class="title2">定位卡号:</strong> {{ item.cardId }}</p>
<p class="title1"><strong class="title2">人员类型:</strong> {{ getPersonTypeName(item.personType) }}</p> <p class="title1"><strong class="title2">人员类型:</strong> {{ getPersonTypeName(item.personType) }}</p>
<p class="title1"><strong class="title2">电话:</strong> {{item.phone}}</p> <p class="title1"><strong class="title2">电话:</strong> {{item.phone}}</p>
<p class="title1"><strong class="title2">部门:</strong> {{item.deptName}}</p> <p class="title1"><strong class="title2">部门:</strong> {{item.deptName}}</p>
......
<template> <template>
<div>人员分布统计</div> <iframe src="http://192.168.2.11/tongji/fenbu" frameborder="0"></iframe>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
......
<script lang="ts" setup>
import { h, onMounted, ref, watch } from 'vue';
import { NButton, NSelect, NSpace, useMessage } from 'naive-ui';
import { Pause } from '@vicons/ionicons5';
import { PlayCircle48Regular } from '@vicons/fluent';
import { create3D } from '@/api/utils/cesium';
import { createModel, createPolyLine, getElevationFromRay, startVehicleMovement, cleanLine, getElevationFromRays } from '@/api/utils/cesiumUtil';
import { remove } from 'nprogress';
import { toConvertLongitudeAndLatitude } from '@/api/utils/coordinateUtil';
import { getModel } from '@/api/utils/cesiumModel';
import { getModelAllApi, getPersonPointApi } from '@/api';
let viewer: any = null;
const range = ref<any>(null);
const personValue = ref('');
const serarchData = ref({
username: '',
startTime: '',
endTime: ''
});
const isShow = ref(false);
const value = ref(null);
const options = ref();
const message = useMessage();
// 进度条相关状态
const speed = ref('1x');
const speedOptions = [
{ label: '1x', value: '50' },
{ label: '10x', value: '100' },
{ label: '20x', value: '200' },
{ label: '30x', value: '300' },
];
const elapsedSeconds = ref(0);
const position = ref([])
// zhangyang
const positions = ref<any[]>([]);
const lineValue = ref<any>();
const model = ref<any>();
const progressFill = ref<HTMLDListElement | null>(null);
let totalSeconds = 3600;
let stepPercent = 100 / totalSeconds;
let currentProgress: any = 0;
let elapsed = 0;
let intervalId: any = null;
// 修改为响应式变量,用于记录暂停状态
const pausedPosition = ref(null);
const remainingSeconds = ref(0);
const isPaused = ref(false);
// 禁用超出一小时范围的日期选择
function disabledDate(current: number, type: string) {
// 如果是日期范围选择器的结束日期,并且已经选择了开始日期
if (type === 'end' && range.value && range.value[0]) {
const startDate = new Date(range.value[0]);
const minEndDate = new Date(startDate);
const maxEndDate = new Date(startDate);
// 设置最大结束时间为开始时间加1小时
maxEndDate.setHours(maxEndDate.getHours() + 1);
// 禁用超出一小时范围的日期
return current > maxEndDate.getTime();
}
return false;
}
// 更新进度
function updateProgress() {
if (elapsed >= totalSeconds) return;
elapsed++;
if (elapsed === totalSeconds) currentProgress = 100;
progressFill.value.style.width = `${currentProgress}%`;
stepPercent = 100 / totalSeconds;
currentProgress += stepPercent;
if (currentProgress > 99) {
isShow.value = false;
}
if (elapsed >= totalSeconds) {
pauseProgress();
resetProgress();
}
}
// 开始进度
function startProgress() {
if(!model.value && !lineValue.value){
message.warning("请选择指定车辆和时间")
}
if (viewer.clock.shouldAnimate) {
// 暂停状态
isShow.value = false;
viewer.clock.shouldAnimate = false;
pauseProgress();
isPaused.value = true;
pausedPosition.value = viewer.clock.currentTime; // 保存当前时间位置
} else if (model.value && lineValue.value) {
isShow.value = true;
// 开始或恢复播放
if (isPaused.value) {
// 从暂停状态恢复,不重置任何进度
viewer.clock.shouldAnimate = true;
if (intervalId) return;
intervalId = setInterval(updateProgress, 1000);
isPaused.value = false;
} else {
// 全新开始
totalSeconds = totalSeconds / speed.value;
startVehicleMovement(viewer, totalSeconds);
if (intervalId) return;
if (elapsed >= totalSeconds) return;
intervalId = setInterval(updateProgress, 1000);
}
}
}
function resetProgress() {
pauseProgress();
stepPercent = 100 / totalSeconds;
currentProgress = 0;
elapsed = 0;
// UI 归零
setTimeout(() => {
progressFill.value.style.width = '0%';
}, 500)
}
// 暂停进度
function pauseProgress() {
if (!intervalId) return;
clearInterval(intervalId);
intervalId = null;
}
// 监听选取的人员
function selectChange(item:any) {
personValue.value = item;
}
// 监听时间范围变化
function watchTimeData(newRange: any) {
if (newRange && newRange.length === 2) {
const startDate = new Date(newRange[0]);
const endDate = new Date(newRange[1]);
// 计算时间差(毫秒)
const durationMs = endDate.getTime() - startDate.getTime();
const durationHours = durationMs / (1000 * 60 * 60);
// 如果超出一小时,给出提示
if (durationHours > 1) {
message.warning('时间范围不能超过一小时,请重新选择');
range.value = null;
serarchData.value.startTime = '';
serarchData.value.endTime = '';
return;
}
serarchData.value.startTime = newRange[0];
serarchData.value.endTime = newRange[1];
// 计算总时长(毫秒转秒)
const durationMs1 = endDate.getTime() - startDate.getTime();
totalSeconds = Math.floor(durationMs1 / 1000);
elapsedSeconds.value = 0;
updateProgress();
}
}
function add3dtiles() {
const CesiumConfig = {
defaultAccessToken:
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI2NTE1OTUxOS1jNTc5LTQwNmMtOWU5My1jNTI3NTIyYzAxNTUiLCJpZCI6MjUwODM5LCJpYXQiOjE3Mjk5MjE1MzV9.xromwPD3oA1e0YsWV035DE5KmYvivkC6fxt344vwObA'
};
Cesium.Ion.defaultAccessToken = CesiumConfig.defaultAccessToken;
viewer = new Cesium.Viewer('cesiumcontainer', {
geocoder: false,
homeButton: false,
infoBox: false,
animation: false,
fullscreenButton: false,
enableCompass: true, // 启用指南针
enableCompassOuterRing: true, // 启用指南针外环
sceneModePicker: false,
timeline: false,
navigationHelpButton: false,
baseLayerPicker: false,
enableZoomControls: false, // 禁用缩放控件
enableDistanceLegend: false // 禁用比例尺
});
viewer.scene.globe.depthTestAgainstTerrain = true;
viewer.scene.globe.depthTestAgainstTerrain = true;
viewer.cesiumWidget.creditContainer.style.display = 'none';
viewer.cesiumWidget.screenSpaceEventHandler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);
getModel().then(item => {
create3D(viewer, item, 0);
});
}
function handleclear() {
serarchData.value.startTime = '';
serarchData.value.endTime = '';
}
function handleReset() {
isShow.value = false;
//删除模型
if (model.value) {
viewer.entities.remove(model.value);
}
viewer.entities.remove(positions.value);
serarchData.value.startTime = '';
serarchData.value.endTime = '';
//进度条清空
resetProgress();
value.value = null;
range.value = null;
//删除线
cleanLine(viewer, positions.value);
personValue.value = '';
positions.value = [];
lineValue.value = [];
}
function handlerClean() {
isShow.value = false;
//删除模型
if (model.value) {
viewer.entities.remove(model.value);
}
//进度条清空
resetProgress();
//删除线
cleanLine(viewer, positions.value);
viewer.entities.remove(positions.value);
positions.value = [];
lineValue.value = [];
}
function selectSpeed(e) {
speed.value = e;
totalSeconds = 3600 / Number(e);
isShow.value = false;
// 重置所有进度相关变量
resetProgress();
// 确保viewer.clock处于正确状态
if (viewer) {
viewer.clock.shouldAnimate = false;
viewer.clock.currentTime = Cesium.JulianDate.now();
}
// 移除并重新创建模型
if (model.value) {
viewer.entities.remove(model.value);
model.value = null;
}
// 确保positions数组有数据才创建模型
if (positions.value && positions.value.length > 0) {
model.value = createModel(positions.value, viewer);
// 确保路线也存在
if (!lineValue.value && positions.value.length >= 2) {
lineValue.value = createPolyLine(positions.value, viewer);
}
// 手动触发开始进度,确保车辆开始移动
// setTimeout(() => {
if (model.value && lineValue.value) {
// 重置isPaused状态,确保是全新开始
isPaused.value = false;
// 直接调用startVehicleMovement开始车辆移动
startVehicleMovement(viewer, totalSeconds);
// 启动进度条更新
if (intervalId) clearInterval(intervalId);
intervalId = setInterval(updateProgress, 1000);
// 更新UI状态
isShow.value = true;
}
// }, 100);
}
}
async function handleSearch() {
handlerClean()
if (serarchData.value.startTime && serarchData.value.endTime) {
let data = {
cardId: personValue.value,
startTime: serarchData.value.startTime,
endTime: serarchData.value.endTime
}
let res = await getPersonPointApi(data);
if(res.data.code == 200) {
for(let item of res.data.data){
const cartographic = Cesium.Cartographic.fromDegrees(item.lon, item.lat);
const height = await getElevationFromRays(cartographic, viewer);
const adjustedHeight = height;
const cartesian = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, adjustedHeight);
positions.value.push(cartesian)
}
model.value = createModel(positions.value, viewer);
undataLine();
} else {
message.error(res.data.msg);
}
} else {
message.info('请先选择您要看的时间点');
}
}
// 添加开始和结束时间显示
function formatDateTime(date: any) {
if (!date) return '';
const d = new Date(date);
return d.toLocaleString('zh-CN', {
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit'
});
}
async function undataLine() {
lineValue.value = createPolyLine(positions.value, viewer);
}
async function search() {
let res = await getModelAllApi();
options.value = res.data.data;
}
onMounted(() => {
add3dtiles();
updateProgress();
search();
});
</script>
<template>
<div class="track-page">
<div style="margin-bottom: 20px; display: flex; justify-content: space-between; align-items: center">
<NSpace>
<div style="display: flex; align-items: center">
人员姓名
<NSpace vertical style="width: 200px; margin-left: 10px">
<NSelect v-model:value="value" :options="options" label-field="realName" value-field="cardId" @update:value="selectChange" />
</NSpace>
</div>
<div style="display: flex; align-items: center; margin-left: 30px">
<NDatePicker v-model:value="range" type="datetimerange" clearable style="margin-left: 10px"
:disabled-date="disabledDate" @update:value="watchTimeData" @clear="handleclear" />
</div>
<NButton color="#2198f2" style="padding: 0px 17px; border-radius: 5px; margin-left: 40px" @click="handleSearch">
查询
</NButton>
<NButton style="padding: 0px 17px; border-radius: 5px" @click="handleReset">重置</NButton>
</NSpace>
</div>
<!-- cesium -->
<div id="cesiumcontainer">
<div class="progress-container">
<!-- 添加开始和结束时间显示 -->
<div class="time-range-display">
<div class="start-time">{{ formatDateTime(serarchData.startTime) }}</div>
<div class="end-time">{{ formatDateTime(serarchData.endTime) }}</div>
</div>
<div class="left-controls">
<NIcon v-if="!isShow" class="control-btn" size="35px" @click="startProgress()">
<PlayCircle48Regular />
</NIcon>
<NIcon v-if="isShow" class="control-btn" size="35px" @click="startProgress()">
<Pause />
</NIcon>
</div>
<!-- 进度条 -->
<div class="progress-bar">
<div ref="progressFill" class="progress-fill"></div>
<div class="progress-dots">
<div class="progress-dot"></div>
<div class="progress-dot"></div>
<div class="progress-dot"></div>
<div class="progress-dot"></div>
<div class="progress-dot"></div>
<div class="progress-dot"></div>
<div class="progress-dot"></div>
<div class="progress-dot"></div>
<div class="progress-dot"></div>
<div class="progress-dot"></div>
<div class="progress-dot"></div>
<div class="progress-dot"></div>
</div>
<div id="progressText" class="progress-text"></div>
</div>
<div class="progress-time">60分</div>
<div class="right-controls">
<NSelect v-model:value="speed" :options="speedOptions" style="width: 80px; margin-left: 10px"
@update:value="selectSpeed" />
</div>
</div>
</div>
</div>
</template>
<style scoped>
#home {
width: 100%;
height: 100%;
}
#cesiumcontainer {
width: 100%;
height: 100%;
position: relative;
overflow: hidden;
box-sizing: border-box;
contain: strict;
isolation: isolate;
}
.progress-container {
position: absolute;
width: 100%;
height: 100px;
background-color: rgba(0, 0, 0, 0.85);
top: 90%;
z-index: 3;
}
.progress-bar {
width: 85%;
height: 15px;
background: rgba(46, 46, 46);
border-radius: 15px;
overflow: hidden;
margin-bottom: 10px;
position: relative;
margin-left: 80px;
margin-top: 40px;
display: flex;
align-items: center;
}
.progress-dots {
position: absolute;
width: 100%;
height: 100%;
display: flex;
justify-content: space-around;
align-items: center;
padding: 0 5%;
box-sizing: border-box;
pointer-events: none;
}
.progress-dot {
width: 12px;
height: 12px;
background-image: url('@/assets/dian.png');
background-size: cover;
background-position: center;
background-repeat: no-repeat;
}
.progress-fill {
height: 100%;
background: linear-gradient(90deg, #00c6ff, #0072ff);
transition: width 0.3s ease;
border-radius: 15px;
box-shadow: 0 0 15px rgba(0, 114, 255, 0.5);
}
.progress-text {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: white;
font-weight: bold;
font-size: 14px;
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);
}
.left-controls {
position: absolute;
color: white;
margin: 30px 0 0 30px;
}
.right-controls {
position: absolute;
top: 30px;
left: 94%;
}
.progress-time {
position: absolute;
top: 35px;
left: 90%;
color: white;
}
.time-range-display {
height: 0px;
display: flex;
justify-content: space-between;
padding: 0px 205px 0px 80px;
color: #e8e8e7;
font-size: 14px;
}
.start-time {
text-align: left;
margin-top: 10px;
}
.end-time {
text-align: right;
margin-top: 10px;
}
.control-btn {
border: none;
color: white;
font-size: 16px;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.3s ease;
}
</style>
...@@ -4,7 +4,7 @@ import { NButton, NSelect, NSpace, useMessage } from 'naive-ui'; ...@@ -4,7 +4,7 @@ import { NButton, NSelect, NSpace, useMessage } from 'naive-ui';
import { Pause } from '@vicons/ionicons5'; import { Pause } from '@vicons/ionicons5';
import { PlayCircle48Regular } from '@vicons/fluent'; import { PlayCircle48Regular } from '@vicons/fluent';
import { create3D } from '@/api/utils/cesium'; import { create3D } from '@/api/utils/cesium';
import { createModel, createPolyLine, getElevationFromRay, startVehicleMovement, cleanLine, getElevationFromRays } from '@/api/utils/cesiumUtil'; import { createModel, createPolyLine, getElevationFromRay, startVehicleMovement, cleanLine, getElevationFromRays, createNewPositionHeight } from '@/api/utils/cesiumUtil';
import { remove } from 'nprogress'; import { remove } from 'nprogress';
import { toConvertLongitudeAndLatitude } from '@/api/utils/coordinateUtil'; import { toConvertLongitudeAndLatitude } from '@/api/utils/coordinateUtil';
import { getModel } from '@/api/utils/cesiumModel'; import { getModel } from '@/api/utils/cesiumModel';
...@@ -18,19 +18,18 @@ const serarchData = ref({ ...@@ -18,19 +18,18 @@ const serarchData = ref({
startTime: '', startTime: '',
endTime: '' endTime: ''
}); });
const cesiumShow = ref(false)
const isShow = ref(false); const isShow = ref(false);
const value = ref(null); const value = ref(null);
const options = ref(); const options = ref();
const message = useMessage(); const message = useMessage();
// 进度条相关状态 // 进度条相关状态
const speed = ref('1x'); const speed = ref('50');
const speedOptions = [ const speedOptions = [
{ label: '1x', value: '50' }, { label: '1x', value: '50' },
{ label: '10x', value: '100' }, { label: '10x', value: '100' },
{ label: '20x', value: '180' }, { label: '20x', value: '200' },
{ label: '30x', value: '280' }, { label: '30x', value: '300' }
{ label: '40x', value: '380' },
{ label: '50x', value: '450' },
]; ];
const elapsedSeconds = ref(0); const elapsedSeconds = ref(0);
const position = ref([]) const position = ref([])
...@@ -77,6 +76,7 @@ function updateProgress() { ...@@ -77,6 +76,7 @@ function updateProgress() {
if (elapsed === totalSeconds) currentProgress = 100; if (elapsed === totalSeconds) currentProgress = 100;
progressFill.value.style.width = `${currentProgress}%`; progressFill.value.style.width = `${currentProgress}%`;
stepPercent = 100 / totalSeconds;
currentProgress += stepPercent; currentProgress += stepPercent;
if (currentProgress > 99) { if (currentProgress > 99) {
...@@ -91,6 +91,9 @@ function updateProgress() { ...@@ -91,6 +91,9 @@ function updateProgress() {
// 开始进度 // 开始进度
function startProgress() { function startProgress() {
if (!model.value && !lineValue.value) {
message.warning("请选择指定车辆和时间")
}
if (viewer.clock.shouldAnimate) { if (viewer.clock.shouldAnimate) {
// 暂停状态 // 暂停状态
isShow.value = false; isShow.value = false;
...@@ -109,7 +112,9 @@ function startProgress() { ...@@ -109,7 +112,9 @@ function startProgress() {
isPaused.value = false; isPaused.value = false;
} else { } else {
// 全新开始 // 全新开始
totalSeconds = 3600 / Number(speed.value);
startVehicleMovement(viewer, totalSeconds); startVehicleMovement(viewer, totalSeconds);
if (intervalId) return; if (intervalId) return;
if (elapsed >= totalSeconds) return; if (elapsed >= totalSeconds) return;
intervalId = setInterval(updateProgress, 1000); intervalId = setInterval(updateProgress, 1000);
...@@ -125,7 +130,7 @@ function resetProgress() { ...@@ -125,7 +130,7 @@ function resetProgress() {
// UI 归零 // UI 归零
setTimeout(() => { setTimeout(() => {
progressFill.value.style.width = '0%'; progressFill.value.style.width = '0%';
}, 500) }, 100)
} }
// 暂停进度 // 暂停进度
...@@ -136,7 +141,7 @@ function pauseProgress() { ...@@ -136,7 +141,7 @@ function pauseProgress() {
} }
// 监听选取的人员 // 监听选取的人员
function selectChange(item:any) { function selectChange(item: any) {
personValue.value = item; personValue.value = item;
} }
// 监听时间范围变化 // 监听时间范围变化
...@@ -213,7 +218,7 @@ function handleReset() { ...@@ -213,7 +218,7 @@ function handleReset() {
//删除模型 //删除模型
if (model.value) { if (model.value) {
viewer.entities.remove(model.value); viewer.entities.remove(model.value);
} }
viewer.entities.remove(positions.value); viewer.entities.remove(positions.value);
serarchData.value.startTime = ''; serarchData.value.startTime = '';
...@@ -229,6 +234,21 @@ function handleReset() { ...@@ -229,6 +234,21 @@ function handleReset() {
lineValue.value = []; lineValue.value = [];
} }
function handlerClean() {
isShow.value = false;
//删除模型
if (model.value) {
viewer.entities.remove(model.value);
}
//进度条清空
resetProgress();
//删除线
cleanLine(viewer, positions.value);
viewer.entities.remove(positions.value);
positions.value = [];
lineValue.value = [];
}
function selectSpeed(e) { function selectSpeed(e) {
speed.value = e; speed.value = e;
totalSeconds = 3600 / Number(e); totalSeconds = 3600 / Number(e);
...@@ -258,7 +278,6 @@ function selectSpeed(e) { ...@@ -258,7 +278,6 @@ function selectSpeed(e) {
} }
// 手动触发开始进度,确保车辆开始移动 // 手动触发开始进度,确保车辆开始移动
// setTimeout(() => {
if (model.value && lineValue.value) { if (model.value && lineValue.value) {
// 重置isPaused状态,确保是全新开始 // 重置isPaused状态,确保是全新开始
isPaused.value = false; isPaused.value = false;
...@@ -272,24 +291,57 @@ function selectSpeed(e) { ...@@ -272,24 +291,57 @@ function selectSpeed(e) {
// 更新UI状态 // 更新UI状态
isShow.value = true; isShow.value = true;
} }
// }, 100);
} }
} }
async function handleSearch() { async function handleSearch() {
handlerClean()
if (serarchData.value.startTime && serarchData.value.endTime) { if (serarchData.value.startTime && serarchData.value.endTime) {
cesiumShow.value = true;
let data = { let data = {
cardId: personValue.value, cardId: personValue.value,
startTime: serarchData.value.startTime, startTime: serarchData.value.startTime,
endTime: serarchData.value.endTime endTime: serarchData.value.endTime
} }
let resHeight = null;
let res = await getPersonPointApi(data); let res = await getPersonPointApi(data);
position.value = res.data.data; if (res.data.code == 200) {
undataLine(); for (let item of res.data.data) {
model.value = createModel(positions.value, viewer); const cartographic = Cesium.Cartographic.fromDegrees(item.lon, item.lat);
const height = await getElevationFromRays(cartographic, viewer);
const adjustedHeight = height;
const cartesian = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, adjustedHeight);
if (resHeight != null) {
let dataHeight = Number(height) - Number(resHeight);
if (dataHeight < 0.5) {
positions.value.push(cartesian);
}
} else {
positions.value.push(cartesian);
}
resHeight = height;
}
let newPositions = await createNewPositionHeight(positions.value, viewer)
model.value = createModel(newPositions, viewer);
undataLine(newPositions);
cesiumShow.value = false;
} else {
message.error(res.data.msg)
cesiumShow.value = false;
}
} else { } else {
message.info('请先选择您要看的时间点'); message.info('请先选择您要看的时间点');
} }
} }
// watch([model, lineValue], ([newModel, newLineValue], [oldModel, oldLineValue]) => {
// if (newModel && newLineValue) {
// cesiumShow.value = false;
// } else {
// cesiumShow.value = true;
// }
// });
// 添加开始和结束时间显示 // 添加开始和结束时间显示
function formatDateTime(date: any) { function formatDateTime(date: any) {
if (!date) return ''; if (!date) return '';
...@@ -303,17 +355,8 @@ function formatDateTime(date: any) { ...@@ -303,17 +355,8 @@ function formatDateTime(date: any) {
}); });
} }
async function undataLine() { function undataLine(newPositions: any) {
for (let i = 0; i < position.value.length; i++) { lineValue.value = createPolyLine(newPositions, viewer);
const cartographic = Cesium.Cartographic.fromDegrees(position.value[i].lon, position.value[i].lat);
const height = await getElevationFromRays(cartographic, viewer);
const adjustedHeight = height;
const cartesian = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, adjustedHeight);
positions.value.push(cartesian);
}
lineValue.value = createPolyLine(positions.value, viewer);
} }
async function search() { async function search() {
...@@ -323,7 +366,9 @@ async function search() { ...@@ -323,7 +366,9 @@ async function search() {
onMounted(() => { onMounted(() => {
add3dtiles(); add3dtiles();
updateProgress(); setTimeout(() => {
updateProgress();
}, 2000);
search(); search();
}); });
</script> </script>
...@@ -335,7 +380,8 @@ onMounted(() => { ...@@ -335,7 +380,8 @@ onMounted(() => {
<div style="display: flex; align-items: center"> <div style="display: flex; align-items: center">
人员姓名 人员姓名
<NSpace vertical style="width: 200px; margin-left: 10px"> <NSpace vertical style="width: 200px; margin-left: 10px">
<NSelect v-model:value="value" :options="options" label-field="realName" value-field="cardId" @update:value="selectChange" /> <NSelect v-model:value="value" :options="options" label-field="realName" value-field="cardId"
@update:value="selectChange" />
</NSpace> </NSpace>
</div> </div>
<div style="display: flex; align-items: center; margin-left: 30px"> <div style="display: flex; align-items: center; margin-left: 30px">
...@@ -350,6 +396,12 @@ onMounted(() => { ...@@ -350,6 +396,12 @@ onMounted(() => {
</NSpace> </NSpace>
</div> </div>
<n-spin class="spinDiv" v-show="cesiumShow">
<template #description>
<span style="color: #2198f2;">加载中...</span>
</template>
</n-spin>
<!-- cesium --> <!-- cesium -->
<div id="cesiumcontainer"> <div id="cesiumcontainer">
<div class="progress-container"> <div class="progress-container">
...@@ -522,4 +574,12 @@ onMounted(() => { ...@@ -522,4 +574,12 @@ onMounted(() => {
justify-content: center; justify-content: center;
transition: all 0.3s ease; transition: all 0.3s ease;
} }
</style> .spinDiv{
width: 87%;
height: 80%;
position: absolute;
top: 169px;
z-index: 999;
background-color: #2e2e2e67;
}
</style>
\ No newline at end of file
<script lang="ts" setup> <script lang="ts" setup>
import { h, onMounted, ref, watch } from 'vue'; import { h, onMounted, ref, watch } from 'vue';
import { NButton, NSelect, NSpace, useMessage } from 'naive-ui'; import { NButton, NSelect, NSpace, useMessage } from 'naive-ui';
import { Pause } from '@vicons/ionicons5'; import { Pause } from '@vicons/ionicons5';
import { PlayCircle48Regular } from '@vicons/fluent'; import { PlayCircle48Regular } from '@vicons/fluent';
import { create3D } from '@/api/utils/cesium'; import { create3D } from '@/api/utils/cesium';
import { createModel, createPolyLine, getElevationFromRay, startVehicleMovement, cleanLine, getElevationFromRays } from '@/api/utils/cesiumCarsUtil'; import { createModel, createPolyLine, getElevationFromRay, startVehicleMovement, cleanLine, getElevationFromRays, createNewPositionHeight } from '@/api/utils/cesiumCarsUtil';
import { remove } from 'nprogress'; import { remove } from 'nprogress';
import { toConvertLongitudeAndLatitude } from '@/api/utils/cesiumCarUtil'; import { toConvertLongitudeAndLatitude } from '@/api/utils/cesiumCarUtil';
import { getModel } from '@/api/utils/cesiumModel'; import { getModel } from '@/api/utils/cesiumModel';
import { getModelAllApi, getPersonPointApi } from '@/api'; import { getCarPointApi, getCarPointCarNumberApi, getModelAllApi, getPersonPointApi } from '@/api';
import { toProjectionCoordinates } from '@/api/utils/coordinateUtil';
let viewer: any = null;
const range = ref<any>(null); let viewer: any = null;
const personValue = ref(''); const range = ref<any>(null);
const serarchData = ref({ const personValue = ref('');
username: '', const cesiumShow = ref(false)
startTime: '', const serarchData = ref({
endTime: '' username: '',
}); startTime: '',
const isShow = ref(false); endTime: ''
const value = ref(null); });
const options = ref(); const isShow = ref(false);
const message = useMessage(); const value = ref(null);
// 进度条相关状态 const options = ref();
const speed = ref('1x'); const message = useMessage();
const speedOptions = [ // 进度条相关状态
{ label: '1x', value: '50' }, const speed = ref('50');
{ label: '10x', value: '100' }, const speedOptions = [
{ label: '20x', value: '200' }, { label: '1x', value: '50' },
{ label: '30x', value: '300' }, { label: '10x', value: '100' },
{ label: '40x', value: '400' }, { label: '20x', value: '200' },
{ label: '50x', value: '500' }, { label: '30x', value: '300' },
]; ];
const elapsedSeconds = ref(0); const elapsedSeconds = ref(0);
const position = ref([]) const position = ref([])
// zhangyang // zhangyang
const positions = ref<any[]>([]); const positions = ref<any[]>([]);
const lineValue = ref<any>(); const lineValue = ref<any>();
const model = ref<any>(); const model = ref<any>();
const progressFill = ref<HTMLDListElement | null>(null); const progressFill = ref<HTMLDListElement | null>(null);
let totalSeconds = 3600; let totalSeconds = 3600;
let stepPercent = 100 / totalSeconds; let stepPercent = 100 / totalSeconds;
let currentProgress: any = 0; let currentProgress: any = 0;
let elapsed = 0; let elapsed = 0;
let intervalId: any = null; let intervalId: any = null;
// 修改为响应式变量,用于记录暂停状态 // 修改为响应式变量,用于记录暂停状态
const pausedPosition = ref(null); const pausedPosition = ref(null);
const remainingSeconds = ref(0); const remainingSeconds = ref(0);
const isPaused = ref(false); const isPaused = ref(false);
// 禁用超出一小时范围的日期选择 // 禁用超出一小时范围的日期选择
function disabledDate(current: number, type: string) { function disabledDate(current: number, type: string) {
// 如果是日期范围选择器的结束日期,并且已经选择了开始日期 // 如果是日期范围选择器的结束日期,并且已经选择了开始日期
if (type === 'end' && range.value && range.value[0]) { if (type === 'end' && range.value && range.value[0]) {
const startDate = new Date(range.value[0]); const startDate = new Date(range.value[0]);
const minEndDate = new Date(startDate); const minEndDate = new Date(startDate);
const maxEndDate = new Date(startDate); const maxEndDate = new Date(startDate);
// 设置最大结束时间为开始时间加1小时 // 设置最大结束时间为开始时间加1小时
maxEndDate.setHours(maxEndDate.getHours() + 1); maxEndDate.setHours(maxEndDate.getHours() + 1);
// 禁用超出一小时范围的日期 // 禁用超出一小时范围的日期
return current > maxEndDate.getTime(); return current > maxEndDate.getTime();
}
return false;
}
// 更新进度
function updateProgress() {
if (elapsed >= totalSeconds) return;
elapsed++;
if (elapsed === totalSeconds) currentProgress = 100;
progressFill.value.style.width = `${currentProgress}%`;
currentProgress += stepPercent;
if (currentProgress > 99) {
isShow.value = false;
}
if (elapsed >= totalSeconds) {
pauseProgress();
resetProgress();
}
} }
return false;
// 开始进度 }
function startProgress() {
if (viewer.clock.shouldAnimate) { // 更新进度
// 暂停状态 function updateProgress() {
isShow.value = false;
viewer.clock.shouldAnimate = false; if (elapsed >= totalSeconds) return;
pauseProgress(); elapsed++;
isPaused.value = true;
pausedPosition.value = viewer.clock.currentTime; // 保存当前时间位置 if (elapsed === totalSeconds) currentProgress = 100;
} else if (model.value && lineValue.value) {
isShow.value = true; progressFill.value.style.width = `${currentProgress}%`;
// 开始或恢复播放 stepPercent = 100 / totalSeconds;
if (isPaused.value) { currentProgress += stepPercent;
// 从暂停状态恢复,不重置任何进度
viewer.clock.shouldAnimate = true;
if (intervalId) return; if (currentProgress > 99) {
intervalId = setInterval(updateProgress, 1000); isShow.value = false;
isPaused.value = false;
} else {
// 全新开始
startVehicleMovement(viewer, totalSeconds);
if (intervalId) return;
if (elapsed >= totalSeconds) return;
intervalId = setInterval(updateProgress, 1000);
}
}
} }
function resetProgress() { if (elapsed >= totalSeconds) {
pauseProgress(); pauseProgress();
stepPercent = 100 / totalSeconds; resetProgress();
currentProgress = 0;
elapsed = 0;
// UI 归零
setTimeout(() => {
progressFill.value.style.width = '0%';
}, 500)
} }
}
// 暂停进度
function pauseProgress() { // 开始进度
if (!intervalId) return; function startProgress() {
clearInterval(intervalId); if (!model.value && !lineValue.value) {
intervalId = null; message.warning("请选择指定车辆和时间")
} }
// 监听选取的人员 if (viewer.clock.shouldAnimate) {
function selectChange(item:any) { // 暂停状态
personValue.value = item; isShow.value = false;
viewer.clock.shouldAnimate = false;
pauseProgress();
isPaused.value = true;
pausedPosition.value = viewer.clock.currentTime; // 保存当前时间位置
} else if (model.value && lineValue.value) {
isShow.value = true;
// 开始或恢复播放
if (isPaused.value) {
// 从暂停状态恢复,不重置任何进度
viewer.clock.shouldAnimate = true;
if (intervalId) return;
intervalId = setInterval(updateProgress, 1000);
isPaused.value = false;
} else {
totalSeconds = 3600 / Number(speed.value)
// 全新开始
startVehicleMovement(viewer, totalSeconds);
if (intervalId) return;
if (elapsed >= totalSeconds) return;
intervalId = setInterval(updateProgress, 1000);
}
} }
// 监听时间范围变化 }
function watchTimeData(newRange: any) {
if (newRange && newRange.length === 2) { function resetProgress() {
const startDate = new Date(newRange[0]); pauseProgress();
const endDate = new Date(newRange[1]); stepPercent = 100 / totalSeconds;
currentProgress = 0;
// 计算时间差(毫秒) elapsed = 0;
const durationMs = endDate.getTime() - startDate.getTime(); // UI 归零
const durationHours = durationMs / (1000 * 60 * 60); setTimeout(() => {
progressFill.value.style.width = '0%';
// 如果超出一小时,给出提示 }, 100)
if (durationHours > 1) { }
message.warning('时间范围不能超过一小时,请重新选择');
range.value = null; // 暂停进度
serarchData.value.startTime = ''; function pauseProgress() {
serarchData.value.endTime = ''; if (!intervalId) return;
return; clearInterval(intervalId);
} intervalId = null;
}
serarchData.value.startTime = newRange[0];
serarchData.value.endTime = newRange[1]; // 监听选取的人员
function selectChange(item: any) {
// 计算总时长(毫秒转秒) console.log(item);
const durationMs1 = endDate.getTime() - startDate.getTime();
totalSeconds = Math.floor(durationMs1 / 1000); personValue.value = item;
elapsedSeconds.value = 0; }
updateProgress(); // 监听时间范围变化
function watchTimeData(newRange: any) {
if (newRange && newRange.length === 2) {
const startDate = new Date(newRange[0]);
const endDate = new Date(newRange[1]);
// 计算时间差(毫秒)
const durationMs = endDate.getTime() - startDate.getTime();
const durationHours = durationMs / (1000 * 60 * 60);
// 如果超出一小时,给出提示
if (durationHours > 1) {
message.warning('时间范围不能超过一小时,请重新选择');
range.value = null;
serarchData.value.startTime = '';
serarchData.value.endTime = '';
return;
} }
serarchData.value.startTime = newRange[0];
serarchData.value.endTime = newRange[1];
// 计算总时长(毫秒转秒)
const durationMs1 = endDate.getTime() - startDate.getTime();
totalSeconds = Math.floor(durationMs1 / 1000);
elapsedSeconds.value = 0;
updateProgress();
} }
}
function add3dtiles() {
const CesiumConfig = { function add3dtiles() {
defaultAccessToken: const CesiumConfig = {
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI2NTE1OTUxOS1jNTc5LTQwNmMtOWU5My1jNTI3NTIyYzAxNTUiLCJpZCI6MjUwODM5LCJpYXQiOjE3Mjk5MjE1MzV9.xromwPD3oA1e0YsWV035DE5KmYvivkC6fxt344vwObA' defaultAccessToken:
}; 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI2NTE1OTUxOS1jNTc5LTQwNmMtOWU5My1jNTI3NTIyYzAxNTUiLCJpZCI6MjUwODM5LCJpYXQiOjE3Mjk5MjE1MzV9.xromwPD3oA1e0YsWV035DE5KmYvivkC6fxt344vwObA'
};
Cesium.Ion.defaultAccessToken = CesiumConfig.defaultAccessToken;
Cesium.Ion.defaultAccessToken = CesiumConfig.defaultAccessToken;
viewer = new Cesium.Viewer('cesiumcontainer', {
geocoder: false, viewer = new Cesium.Viewer('cesiumcontainer', {
homeButton: false, geocoder: false,
infoBox: false, homeButton: false,
animation: false, infoBox: false,
fullscreenButton: false, animation: false,
enableCompass: true, // 启用指南针 fullscreenButton: false,
enableCompassOuterRing: true, // 启用指南针外环 enableCompass: true, // 启用指南针
sceneModePicker: false, enableCompassOuterRing: true, // 启用指南针外环
timeline: false, sceneModePicker: false,
navigationHelpButton: false, timeline: false,
baseLayerPicker: false, navigationHelpButton: false,
enableZoomControls: false, // 禁用缩放控件 baseLayerPicker: false,
enableDistanceLegend: false // 禁用比例尺 enableZoomControls: false, // 禁用缩放控件
}); enableDistanceLegend: false // 禁用比例尺
});
viewer.scene.globe.depthTestAgainstTerrain = true;
viewer.scene.globe.depthTestAgainstTerrain = true; viewer.scene.globe.depthTestAgainstTerrain = true;
viewer.cesiumWidget.creditContainer.style.display = 'none'; viewer.scene.globe.depthTestAgainstTerrain = true;
viewer.cesiumWidget.screenSpaceEventHandler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK); viewer.cesiumWidget.creditContainer.style.display = 'none';
viewer.cesiumWidget.screenSpaceEventHandler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);
getModel().then(item => {
create3D(viewer, item, 0); getModel().then(item => {
}); create3D(viewer, item, 0);
});
}
function handleclear() {
serarchData.value.startTime = '';
serarchData.value.endTime = '';
}
function handleReset() {
isShow.value = false;
//删除模型
if (model.value) {
viewer.entities.remove(model.value);
} }
//进度条清空
function handleclear() { resetProgress();
serarchData.value.startTime = ''; //删除线
serarchData.value.endTime = ''; cleanLine(viewer, positions.value);
value.value = null;
range.value = null;
viewer.entities.remove(positions.value);
positions.value = [];
lineValue.value = [];
}
function handlerClean() {
isShow.value = false;
//删除模型
if (model.value) {
viewer.entities.remove(model.value);
} }
//进度条清空
function handleReset() { resetProgress();
isShow.value = false; //删除线
//删除模型 cleanLine(viewer, positions.value);
if (model.value) { viewer.entities.remove(positions.value);
viewer.entities.remove(model.value); positions.value = [];
lineValue.value = [];
} }
//进度条清空
resetProgress(); function selectSpeed(e) {
//删除线 speed.value = e;
cleanLine(viewer, positions.value); totalSeconds = 3600 / Number(e);
value.value = null; isShow.value = false;
range.value = null; // 重置所有进度相关变量
viewer.entities.remove(positions.value); resetProgress();
positions.value = [];
lineValue.value = []; // 确保viewer.clock处于正确状态
if (viewer) {
viewer.clock.shouldAnimate = false;
viewer.clock.currentTime = Cesium.JulianDate.now();
} }
function selectSpeed(e) { // 移除并重新创建模型
speed.value = e; if (model.value) {
totalSeconds = 3600 / Number(e); viewer.entities.remove(model.value);
isShow.value = false; model.value = null;
// 重置所有进度相关变量 }
resetProgress();
// 确保positions数组有数据才创建模型
// 确保viewer.clock处于正确状态 if (positions.value && positions.value.length > 0) {
if (viewer) { model.value = createModel(positions.value, viewer);
viewer.clock.shouldAnimate = false;
viewer.clock.currentTime = Cesium.JulianDate.now(); // 确保路线也存在
} if (!lineValue.value && positions.value.length >= 2) {
lineValue.value = createPolyLine(positions.value, viewer);
// 移除并重新创建模型
if (model.value) {
viewer.entities.remove(model.value);
model.value = null;
} }
// 确保positions数组有数据才创建模型 // 手动触发开始进度,确保车辆开始移动
if (positions.value && positions.value.length > 0) { // setTimeout(() => {
model.value = createModel(positions.value, viewer); if (model.value && lineValue.value) {
// 重置isPaused状态,确保是全新开始
// 确保路线也存在 isPaused.value = false;
if (!lineValue.value && positions.value.length >= 2) { // 直接调用startVehicleMovement开始车辆移动
lineValue.value = createPolyLine(positions.value, viewer); startVehicleMovement(viewer, totalSeconds);
}
// 启动进度条更新
// 手动触发开始进度,确保车辆开始移动 if (intervalId) clearInterval(intervalId);
// setTimeout(() => { intervalId = setInterval(updateProgress, 1000);
if (model.value && lineValue.value) {
// 重置isPaused状态,确保是全新开始 // 更新UI状态
isPaused.value = false; isShow.value = true;
// 直接调用startVehicleMovement开始车辆移动
startVehicleMovement(viewer, totalSeconds);
// 启动进度条更新
if (intervalId) clearInterval(intervalId);
intervalId = setInterval(updateProgress, 1000);
// 更新UI状态
isShow.value = true;
}
// }, 100);
} }
// }, 100);
} }
async function handleSearch() { }
if (serarchData.value.startTime && serarchData.value.endTime) { async function handleSearch() {
let data = { handlerClean()
cardId: personValue.value, if (serarchData.value.startTime && serarchData.value.endTime) {
startTime: serarchData.value.startTime, cesiumShow.value = true;
endTime: serarchData.value.endTime let data = {
carNumber: personValue.value,
startTime: serarchData.value.startTime,
endTime: serarchData.value.endTime
}
let resHeight = null;
let res = await getCarPointApi(data);
if (res.data.code == 200) {
for (let item of res.data.data) {
const cartographic = Cesium.Cartographic.fromDegrees(item.lon, item.lat);
const height = await getElevationFromRays(cartographic, viewer);
const adjustedHeight = height;
const cartesian = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, adjustedHeight);
if (resHeight != null) {
let dataHeight = Number(height) - Number(resHeight);
if (dataHeight < 0.5) {
positions.value.push(cartesian);
}
} else {
positions.value.push(cartesian);
}
resHeight = height;
} }
let res = await getPersonPointApi(data);
position.value = res.data.data; let newPositions = await createNewPositionHeight(positions.value, viewer)
undataLine();
model.value = createModel(positions.value, viewer); model.value = createModel(newPositions, viewer);
undataLine(newPositions);
cesiumShow.value = false;
} else { } else {
message.info('请先选择您要看的时间点'); message.error(res.data.msg);
cesiumShow.value = false;
} }
} else {
message.info('请先选择您要看的时间点');
} }
// 添加开始和结束时间显示 }
function formatDateTime(date: any) {
if (!date) return ''; // watch([model.value, lineValue.value], ([newModel, newLineValue], [oldModel, oldLineValue]) => {
const d = new Date(date); // if (newModel && newLineValue) {
return d.toLocaleString('zh-CN', { // cesiumShow.value = false;
year: 'numeric', // } else {
month: '2-digit', // cesiumShow.value = true;
day: '2-digit', // }
hour: '2-digit', // },{ deep: true });
minute: '2-digit'
}); // 添加开始和结束时间显示
} function formatDateTime(date: any) {
if (!date) return '';
async function undataLine() { const d = new Date(date);
for (let i = 0; i < position.value.length; i++) { return d.toLocaleString('zh-CN', {
const cartographic = Cesium.Cartographic.fromDegrees(position.value[i].lon, position.value[i].lat); year: 'numeric',
const height = await getElevationFromRays(cartographic, viewer); month: '2-digit',
const adjustedHeight = height; day: '2-digit',
const cartesian = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, adjustedHeight); hour: '2-digit',
positions.value.push(cartesian); minute: '2-digit'
}
lineValue.value = createPolyLine(positions.value, viewer);
}
async function search() {
let res = await getModelAllApi();
options.value = res.data.data;
}
onMounted(() => {
add3dtiles();
updateProgress();
search();
}); });
</script> }
<template> async function undataLine(newPositions: any) {
<div class="track-page"> lineValue.value = createPolyLine(newPositions, viewer);
<div style="margin-bottom: 20px; display: flex; justify-content: space-between; align-items: center"> }
<NSpace>
<div style="display: flex; align-items: center"> async function search() {
车牌号 let res = await getCarPointCarNumberApi();
<NSpace vertical style="width: 200px; margin-left: 10px"> options.value = res.data.data;
<NSelect v-model:value="value" :options="options" label-field="realName" value-field="cardId" @update:value="selectChange" /> }
</NSpace>
</div> onMounted(() => {
<div style="display: flex; align-items: center; margin-left: 30px"> add3dtiles();
<NDatePicker v-model:value="range" type="datetimerange" clearable style="margin-left: 10px" updateProgress();
:disabled-date="disabledDate" @update:value="watchTimeData" @clear="handleclear" /> search();
</div> });
</script>
<NButton color="#2198f2" style="padding: 0px 17px; border-radius: 5px; margin-left: 40px" @click="handleSearch">
查询 <template>
</NButton> <div class="track-page">
<NButton style="padding: 0px 17px; border-radius: 5px" @click="handleReset">重置</NButton> <div style="margin-bottom: 20px; display: flex; justify-content: space-between; align-items: center">
</NSpace> <NSpace>
</div> <div style="display: flex; align-items: center">
车牌号
<!-- cesium --> <NSpace vertical style="width: 200px; margin-left: 10px">
<div id="cesiumcontainer"> <NSelect v-model:value="value" :options="options" label-field="carNumber" value-field="carNumber"
<div class="progress-container"> @update:value="selectChange" />
<!-- 添加开始和结束时间显示 --> </NSpace>
<div class="time-range-display"> </div>
<div class="start-time">{{ formatDateTime(serarchData.startTime) }}</div> <div style="display: flex; align-items: center; margin-left: 30px">
<div class="end-time">{{ formatDateTime(serarchData.endTime) }}</div> <NDatePicker v-model:value="range" type="datetimerange" clearable style="margin-left: 10px"
</div> :disabled-date="disabledDate" @update:value="watchTimeData" @clear="handleclear" />
<div class="left-controls"> </div>
<NIcon v-if="!isShow" class="control-btn" size="35px" @click="startProgress()">
<PlayCircle48Regular /> <NButton color="#2198f2" style="padding: 0px 17px; border-radius: 5px; margin-left: 40px" @click="handleSearch">
</NIcon> 查询
<NIcon v-if="isShow" class="control-btn" size="35px" @click="startProgress()"> </NButton>
<Pause /> <NButton style="padding: 0px 17px; border-radius: 5px" @click="handleReset">重置</NButton>
</NIcon> </NSpace>
</div> </div>
<!-- 进度条 --> <!-- 加载中 -->
<div class="progress-bar"> <n-spin class="spinDiv" v-show="cesiumShow">
<div ref="progressFill" class="progress-fill"></div> <template #description>
<div class="progress-dots"> <span style="color: #2198f2;">加载中...</span>
<div class="progress-dot"></div> </template>
<div class="progress-dot"></div> </n-spin>
<div class="progress-dot"></div> <!-- cesium -->
<div class="progress-dot"></div> <div id="cesiumcontainer">
<div class="progress-dot"></div> <div class="progress-container">
<div class="progress-dot"></div> <!-- 添加开始和结束时间显示 -->
<div class="progress-dot"></div> <div class="time-range-display">
<div class="progress-dot"></div> <div class="start-time">{{ formatDateTime(serarchData.startTime) }}</div>
<div class="progress-dot"></div> <div class="end-time">{{ formatDateTime(serarchData.endTime) }}</div>
<div class="progress-dot"></div> </div>
<div class="progress-dot"></div> <div class="left-controls">
<div class="progress-dot"></div> <NIcon v-if="!isShow" class="control-btn" size="35px" @click="startProgress()">
</div> <PlayCircle48Regular />
<div id="progressText" class="progress-text"></div> </NIcon>
</div> <NIcon v-if="isShow" class="control-btn" size="35px" @click="startProgress()">
<div class="progress-time">60分</div> <Pause />
<div class="right-controls"> </NIcon>
<NSelect v-model:value="speed" :options="speedOptions" style="width: 80px; margin-left: 10px" </div>
@update:value="selectSpeed" /> <!-- 进度条 -->
<div class="progress-bar">
<div ref="progressFill" class="progress-fill"></div>
<div class="progress-dots">
<div class="progress-dot"></div>
<div class="progress-dot"></div>
<div class="progress-dot"></div>
<div class="progress-dot"></div>
<div class="progress-dot"></div>
<div class="progress-dot"></div>
<div class="progress-dot"></div>
<div class="progress-dot"></div>
<div class="progress-dot"></div>
<div class="progress-dot"></div>
<div class="progress-dot"></div>
<div class="progress-dot"></div>
</div> </div>
<div id="progressText" class="progress-text"></div>
</div>
<div class="progress-time">60分</div>
<div class="right-controls">
<NSelect v-model:value="speed" :options="speedOptions" style="width: 80px; margin-left: 10px"
@update:value="selectSpeed" />
</div> </div>
</div> </div>
</div> </div>
</template> </div>
</template>
<style scoped>
#home { <style scoped>
width: 100%; #home {
height: 100%; width: 100%;
} height: 100%;
}
#cesiumcontainer {
width: 100%; #cesiumcontainer {
height: 100%; width: 100%;
position: relative; height: 100%;
overflow: hidden; position: relative;
box-sizing: border-box; overflow: hidden;
contain: strict; box-sizing: border-box;
isolation: isolate; contain: strict;
} isolation: isolate;
}
.progress-container {
position: absolute; .progress-container {
width: 100%; position: absolute;
height: 100px; width: 100%;
background-color: rgba(0, 0, 0, 0.85); height: 100px;
top: 90%; background-color: rgba(0, 0, 0, 0.85);
z-index: 3; top: 90%;
} z-index: 3;
}
.progress-bar {
width: 85%; .progress-bar {
height: 15px; width: 85%;
background: rgba(46, 46, 46); height: 15px;
border-radius: 15px; background: rgba(46, 46, 46);
overflow: hidden; border-radius: 15px;
margin-bottom: 10px; overflow: hidden;
position: relative; margin-bottom: 10px;
margin-left: 80px; position: relative;
margin-top: 40px; margin-left: 80px;
display: flex; margin-top: 40px;
align-items: center; display: flex;
} align-items: center;
}
.progress-dots {
position: absolute; .progress-dots {
width: 100%; position: absolute;
height: 100%; width: 100%;
display: flex; height: 100%;
justify-content: space-around; display: flex;
align-items: center; justify-content: space-around;
padding: 0 5%; align-items: center;
box-sizing: border-box; padding: 0 5%;
pointer-events: none; box-sizing: border-box;
} pointer-events: none;
}
.progress-dot {
width: 12px; .progress-dot {
height: 12px; width: 12px;
background-image: url('@/assets/dian.png'); height: 12px;
background-size: cover; background-image: url('@/assets/dian.png');
background-position: center; background-size: cover;
background-repeat: no-repeat; background-position: center;
} background-repeat: no-repeat;
}
.progress-fill {
height: 100%; .progress-fill {
background: linear-gradient(90deg, #00c6ff, #0072ff); height: 100%;
transition: width 0.3s ease; background: linear-gradient(90deg, #00c6ff, #0072ff);
border-radius: 15px; transition: width 0.3s ease;
box-shadow: 0 0 15px rgba(0, 114, 255, 0.5); border-radius: 15px;
} box-shadow: 0 0 15px rgba(0, 114, 255, 0.5);
}
.progress-text {
position: absolute; .progress-text {
top: 50%; position: absolute;
left: 50%; top: 50%;
transform: translate(-50%, -50%); left: 50%;
color: white; transform: translate(-50%, -50%);
font-weight: bold; color: white;
font-size: 14px; font-weight: bold;
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.5); font-size: 14px;
} text-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);
}
.left-controls {
position: absolute; .left-controls {
color: white; position: absolute;
margin: 30px 0 0 30px; color: white;
} margin: 30px 0 0 30px;
}
.right-controls {
position: absolute; .right-controls {
top: 30px; position: absolute;
left: 94%; top: 30px;
} left: 94%;
}
.progress-time {
position: absolute; .progress-time {
top: 35px; position: absolute;
left: 90%; top: 35px;
color: white; left: 90%;
} color: white;
}
.time-range-display {
height: 0px; .time-range-display {
display: flex; height: 0px;
justify-content: space-between; display: flex;
padding: 0px 205px 0px 80px; justify-content: space-between;
color: #e8e8e7; padding: 0px 205px 0px 80px;
font-size: 14px; color: #e8e8e7;
} font-size: 14px;
}
.start-time {
text-align: left; .start-time {
margin-top: 10px; text-align: left;
} margin-top: 10px;
}
.end-time {
text-align: right; .end-time {
margin-top: 10px; text-align: right;
} margin-top: 10px;
}
.control-btn {
border: none; .control-btn {
color: white; border: none;
font-size: 16px; color: white;
cursor: pointer; font-size: 16px;
display: flex; cursor: pointer;
align-items: center; display: flex;
justify-content: center; align-items: center;
transition: all 0.3s ease; justify-content: center;
} transition: all 0.3s ease;
</style> }
\ No newline at end of file .spinDiv {
width: 87%;
height: 80%;
position: absolute;
top: 169px;
z-index: 999;
background-color: #2e2e2e67;
}
</style>
\ No newline at end of file
...@@ -262,6 +262,8 @@ function posSubmit() { ...@@ -262,6 +262,8 @@ function posSubmit() {
message.success('修改成功') message.success('修改成功')
search() search()
passwordModal.value = false; passwordModal.value = false;
localStorage.removeItem('token');
window.location.href = '/login';
}else{ }else{
message.error(res.data.msg) message.error(res.data.msg)
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment