fix: 修复社区版bug

This commit is contained in:
XieYongHong 2023-04-18 09:24:16 +08:00 committed by GitHub
parent 486d7250de
commit 57d8521d96
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
173 changed files with 2344 additions and 1550 deletions

View File

@ -25,7 +25,7 @@
"event-source-polyfill": "^1.0.31",
"global": "^4.4.0",
"jetlinks-store": "^0.0.3",
"jetlinks-ui-components": "^1.0.5",
"jetlinks-ui-components": "1.0.5",
"js-cookie": "^3.0.1",
"less": "^4.1.3",
"less-loader": "^11.1.0",
@ -64,6 +64,7 @@
"typescript": "^4.9.3",
"vite": "^4.0.0",
"vite-plugin-html": "^3.2.0",
"vite-plugin-progress": "^0.0.7",
"vite-plugin-style-import": "^2.0.0",
"vite-plugin-vue-setup-extend": "^0.4.0",
"vue-tsc": "^1.0.11"

View File

@ -337,9 +337,6 @@ export function JetlinksVueResolver(options: JetlinksVueResolverOptions = {}): a
options.packageName = _isJetlinks ? 'jetlinks-ui-components' : 'ant-design-vue'
const path = `${options.packageName}/${options.cjs ? 'lib' : 'es'}`
const stylePath = getSideEffects(importName, options, _isAntd)
if (_isJetlinks) {
console.log(name, importName, stylePath)
}
return {
name: importName,
from: path,

View File

@ -43,7 +43,6 @@ export function optimizeDeps() {
]
let concat = config.optimizeDeps.include.concat(components)
config.optimizeDeps.include = Array.from(new Set(concat))
console.log(config.optimizeDeps.include)
}
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 164 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 102 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.7 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 891 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 7.2 KiB

View File

@ -0,0 +1,57 @@
<svg width="92" height="91" viewBox="0 0 92 91" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M4.56306 81.9135L45.5027 58.4234L86.4422 81.9135L86.4422 91.0396L45.5026 113.996L4.56314 91.0397L4.56306 81.9135Z" fill="white"/>
<path d="M4.92969 82.5615L46.2592 105.436V114.254L4.92969 91.3798V82.5615Z" fill="url(#paint0_linear_2942_6715)"/>
<path d="M87.0684 82.5615L45.7389 105.436V114.254L87.0684 91.3798V82.5615Z" fill="#B8BFD5"/>
<g opacity="0.7">
<line x1="5.41211" y1="22.7676" x2="5.41211" y2="64.6693" stroke="#4980F7" stroke-opacity="0.2" stroke-width="2" stroke-dasharray="3 3"/>
<line x1="45.9277" y1="4.57666" x2="45.9277" y2="36.6577" stroke="#4980F7" stroke-opacity="0.2" stroke-width="2" stroke-dasharray="3 3"/>
<line x1="86.0352" y1="22.7676" x2="86.0351" y2="64.6693" stroke="#4980F7" stroke-opacity="0.2" stroke-width="2" stroke-dasharray="3 3"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M45.3579 0L41.6543 3.70362L45.3579 7.40725L49.0615 3.70362L45.3579 0ZM45.3579 1.85181L43.506 3.70362L45.3579 5.55543L47.2097 3.70362L45.3579 1.85181Z" fill="#4980F7"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M86.1196 20.4336L82.416 24.1372L86.1196 27.8408L89.8233 24.1372L86.1196 20.4336ZM86.1196 22.2854L84.2678 24.1372L86.1196 25.989L87.9714 24.1372L86.1196 22.2854Z" fill="#4980F7"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M4.8423 20.4336L1.13867 24.1372L4.8423 27.8408L8.54592 24.1372L4.8423 20.4336ZM4.84224 22.2854L2.99042 24.1372L4.84224 25.989L6.69405 24.1372L4.84224 22.2854Z" fill="#4980F7"/>
</g>
<path d="M86.4213 83.2303V38.2187L45.5017 15.4351L4.58203 38.2187V83.2303L45.5017 105.458L86.4213 83.2303Z" fill="white"/>
<path d="M45.5017 16.0073L85.9213 38.5126V82.9329L45.5017 104.889L5.08203 82.9329V38.5126L45.5017 16.0073Z" stroke="#5995F5" stroke-opacity="0.3"/>
<path d="M86.0533 38.3097L45.502 15.5583V60.2017L86.0533 81.93V38.3097Z" fill="url(#paint1_linear_2942_6715)" fill-opacity="0.1"/>
<path opacity="0.6" d="M5.2168 82.5623L45.5015 60.2822L87.096 82.5623L87.096 82.5224L46.1564 105.479L5.2168 82.5623Z" fill="url(#paint2_linear_2942_6715)"/>
<rect x="44.4785" y="15.8469" width="2.04598" height="2.04598" rx="1.02299" fill="#5995F5"/>
<rect x="4.58203" y="37.9421" width="2.04598" height="2.04598" rx="1.02299" fill="#5995F5"/>
<rect x="4.58203" y="80.9075" width="2.04598" height="2.04598" rx="1.02299" fill="#5995F5"/>
<rect x="84.375" y="37.9421" width="2.04598" height="2.04598" rx="1.02299" fill="#5995F5"/>
<rect x="84.375" y="80.9075" width="2.04598" height="2.04598" rx="1.02299" fill="#5995F5"/>
<path d="M46.558 30.875L71.116 43.0039L46.558 54.9314L22 43.0039L46.558 30.875Z" fill="url(#paint3_linear_2942_6715)"/>
<path d="M71.1166 43.0073L46.5586 54.9348V90.2174L71.1166 78.29V43.0073Z" fill="url(#paint4_linear_2942_6715)"/>
<path d="M46.558 54.9348L22 43.0073V78.29L46.558 90.2174V54.9348Z" fill="url(#paint5_linear_2942_6715)"/>
<path d="M50.0664 58.5516L68.5096 49.731V52.1366L50.0664 60.9573V58.5516Z" fill="#DFE7FF"/>
<path d="M50.0664 69.7733L68.5096 60.9526V63.3583L50.0664 72.1789V69.7733Z" fill="#DFE7FF"/>
<path d="M50.0664 81.0074L68.5096 72.1868V74.5924L50.0664 83.4131V81.0074Z" fill="#DFE7FF"/>
<ellipse cx="25.9816" cy="51.4576" rx="1.60376" ry="2.0047" transform="rotate(-29.2048 25.9816 51.4576)" fill="#D0DBFF"/>
<ellipse cx="25.9816" cy="62.6795" rx="1.60376" ry="2.0047" transform="rotate(-29.2048 25.9816 62.6795)" fill="#D0DBFF"/>
<ellipse cx="25.9816" cy="73.9012" rx="1.60376" ry="2.0047" transform="rotate(-29.2048 25.9816 73.9012)" fill="#D0DBFF"/>
<defs>
<linearGradient id="paint0_linear_2942_6715" x1="8.51207" y1="91.3851" x2="42.5572" y2="109.717" gradientUnits="userSpaceOnUse">
<stop stop-color="#C9D8FF"/>
<stop offset="1" stop-color="white"/>
</linearGradient>
<linearGradient id="paint1_linear_2942_6715" x1="65.7776" y1="15.5583" x2="65.7776" y2="81.93" gradientUnits="userSpaceOnUse">
<stop offset="0.0667851" stop-color="#7A9EF4"/>
<stop offset="1" stop-color="#EFF1F9"/>
</linearGradient>
<linearGradient id="paint2_linear_2942_6715" x1="25.6761" y1="62.0627" x2="66.6355" y2="103.022" gradientUnits="userSpaceOnUse">
<stop offset="0.0001" stop-color="#A0B4FF"/>
<stop offset="1" stop-color="#B5C4FD" stop-opacity="0.01"/>
</linearGradient>
<linearGradient id="paint3_linear_2942_6715" x1="46.558" y1="30.875" x2="46.558" y2="90.214" gradientUnits="userSpaceOnUse">
<stop stop-color="#C5D7FF"/>
<stop offset="1" stop-color="#ADC6FF" stop-opacity="0"/>
</linearGradient>
<linearGradient id="paint4_linear_2942_6715" x1="50.7446" y1="57.0796" x2="67.4916" y2="57.2512" gradientUnits="userSpaceOnUse">
<stop stop-color="#A0B8FF"/>
<stop offset="0.963422" stop-color="#6A8DFF"/>
</linearGradient>
<linearGradient id="paint5_linear_2942_6715" x1="26.186" y1="57.0796" x2="42.933" y2="57.2512" gradientUnits="userSpaceOnUse">
<stop stop-color="#92B2FF"/>
<stop offset="1" stop-color="#ADC2FE"/>
</linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

After

Width:  |  Height:  |  Size: 7.6 KiB

View File

@ -0,0 +1,67 @@
<svg width="92" height="91" viewBox="0 0 92 91" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M4.56306 81.9135L45.5027 58.4234L86.4422 81.9135L86.4422 91.0396L45.5026 113.996L4.56314 91.0397L4.56306 81.9135Z" fill="white"/>
<path d="M4.92871 82.5615L46.2582 105.436V114.254L4.92871 91.3798V82.5615Z" fill="url(#paint0_linear_2942_6631)"/>
<path d="M87.0684 82.5615L45.7389 105.436V114.254L87.0684 91.3798V82.5615Z" fill="#B8BFD5"/>
<g opacity="0.7">
<line x1="5.41309" y1="22.7676" x2="5.41308" y2="64.6693" stroke="#4980F7" stroke-opacity="0.2" stroke-width="2" stroke-dasharray="3 3"/>
<line x1="45.9287" y1="4.57666" x2="45.9287" y2="36.6577" stroke="#4980F7" stroke-opacity="0.2" stroke-width="2" stroke-dasharray="3 3"/>
<line x1="86.0371" y1="22.7676" x2="86.0371" y2="64.6693" stroke="#4980F7" stroke-opacity="0.2" stroke-width="2" stroke-dasharray="3 3"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M45.3589 0L41.6553 3.70362L45.3589 7.40725L49.0625 3.70362L45.3589 0ZM45.3588 1.85181L43.507 3.70362L45.3588 5.55543L47.2106 3.70362L45.3588 1.85181Z" fill="#4980F7"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M86.1216 20.4336L82.418 24.1372L86.1216 27.8408L89.8252 24.1372L86.1216 20.4336ZM86.1215 22.2854L84.2697 24.1372L86.1215 25.989L87.9733 24.1372L86.1215 22.2854Z" fill="#4980F7"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M4.84327 20.4336L1.13965 24.1372L4.84327 27.8408L8.5469 24.1372L4.84327 20.4336ZM4.84321 22.2854L2.9914 24.1372L4.84321 25.989L6.69502 24.1372L4.84321 22.2854Z" fill="#4980F7"/>
</g>
<path d="M86.4223 83.2303V38.2187L45.5026 15.4351L4.58301 38.2187V83.2303L45.5026 105.458L86.4223 83.2303Z" fill="white"/>
<path d="M45.5026 16.0073L85.9223 38.5126V82.9329L45.5026 104.889L5.08301 82.9329V38.5126L45.5026 16.0073Z" stroke="#5995F5" stroke-opacity="0.3"/>
<path d="M86.0543 38.3097L45.5029 15.5583V60.2017L86.0543 81.93V38.3097Z" fill="url(#paint1_linear_2942_6631)" fill-opacity="0.1"/>
<path opacity="0.6" d="M5.21777 82.5623L45.5025 60.2822L87.097 82.5623L87.0969 82.5224L46.1574 105.479L5.21777 82.5623Z" fill="url(#paint2_linear_2942_6631)"/>
<rect x="44.4795" y="15.8469" width="2.04598" height="2.04598" rx="1.02299" fill="#5995F5"/>
<rect x="4.58301" y="37.9421" width="2.04598" height="2.04598" rx="1.02299" fill="#5995F5"/>
<rect x="4.58301" y="80.9075" width="2.04598" height="2.04598" rx="1.02299" fill="#5995F5"/>
<rect x="84.375" y="37.9421" width="2.04598" height="2.04598" rx="1.02299" fill="#5995F5"/>
<rect x="84.375" y="80.9075" width="2.04598" height="2.04598" rx="1.02299" fill="#5995F5"/>
<path d="M15.7725 44.9007L45.4099 31L74.2605 44.9007L45.4099 60.8997L15.7725 44.9007Z" fill="url(#paint3_linear_2942_6631)"/>
<path d="M30.46 45.431L45.0793 38.6025L59.3105 45.431L45.0793 53.2901L30.46 45.431Z" fill="url(#paint4_linear_2942_6631)"/>
<path d="M15.7725 76.3798V44.906L45.4099 60.9054V95.0015L15.7725 76.3798Z" fill="#D7DBFB"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M28.9119 58.7642L21.3242 54.7348L21.3243 54.022L29.5442 58.4481L30.4927 61.0579L35.39 63.9437L35.3901 64.7039L29.9063 61.5846L28.9119 58.7642Z" fill="url(#paint5_linear_2942_6631)"/>
<path d="M21.3242 72.4324V58.2209V55.6917L28.5957 59.4855L29.228 62.0147L38.3964 67.0729V82.5476L21.3242 72.4324Z" fill="url(#paint6_linear_2942_6631)"/>
<path d="M74.2607 75.8548L45.4102 95.0011V60.905L74.2607 44.906V75.8548Z" fill="url(#paint7_linear_2942_6631)"/>
<path d="M66.6541 72.9249L53.0156 82.1472V65.7239L66.6541 58.0176V72.9249Z" fill="url(#paint8_linear_2942_6631)"/>
<defs>
<linearGradient id="paint0_linear_2942_6631" x1="8.5111" y1="91.3851" x2="42.5562" y2="109.717" gradientUnits="userSpaceOnUse">
<stop stop-color="#C9D8FF"/>
<stop offset="1" stop-color="white"/>
</linearGradient>
<linearGradient id="paint1_linear_2942_6631" x1="65.7786" y1="15.5583" x2="65.7786" y2="81.93" gradientUnits="userSpaceOnUse">
<stop offset="0.0667851" stop-color="#7A9EF4"/>
<stop offset="1" stop-color="#EFF1F9"/>
</linearGradient>
<linearGradient id="paint2_linear_2942_6631" x1="25.6771" y1="62.0627" x2="66.6365" y2="103.022" gradientUnits="userSpaceOnUse">
<stop offset="0.0001" stop-color="#A0B4FF"/>
<stop offset="1" stop-color="#B5C4FD" stop-opacity="0.01"/>
</linearGradient>
<linearGradient id="paint3_linear_2942_6631" x1="45.0165" y1="31" x2="45.0165" y2="60.8997" gradientUnits="userSpaceOnUse">
<stop stop-color="#ADC6FF"/>
<stop offset="1" stop-color="#ADC6FF" stop-opacity="0"/>
</linearGradient>
<linearGradient id="paint4_linear_2942_6631" x1="44.8852" y1="37.9337" x2="44.8852" y2="52.9485" gradientUnits="userSpaceOnUse">
<stop stop-color="#7699FD" stop-opacity="0.38"/>
<stop offset="1" stop-color="#7699FD"/>
</linearGradient>
<linearGradient id="paint5_linear_2942_6631" x1="23.3602" y1="56.3189" x2="28.4977" y2="68.2627" gradientUnits="userSpaceOnUse">
<stop stop-color="#007C52"/>
<stop offset="1" stop-color="#007C52" stop-opacity="0.25"/>
</linearGradient>
<linearGradient id="paint6_linear_2942_6631" x1="24.2342" y1="63.6968" x2="35.8758" y2="63.8426" gradientUnits="userSpaceOnUse">
<stop stop-color="#6F9AFE"/>
<stop offset="1" stop-color="#A6BDFF"/>
</linearGradient>
<linearGradient id="paint7_linear_2942_6631" x1="74.3178" y1="60.1441" x2="45.7442" y2="82.4264" gradientUnits="userSpaceOnUse">
<stop stop-color="#97B6FF"/>
<stop offset="1" stop-color="white"/>
</linearGradient>
<linearGradient id="paint8_linear_2942_6631" x1="55.3404" y1="65.21" x2="64.6407" y2="65.3136" gradientUnits="userSpaceOnUse">
<stop stop-color="#B9CBFF"/>
<stop offset="0.963422" stop-color="#6A8DFF"/>
</linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 199 KiB

After

Width:  |  Height:  |  Size: 210 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 551 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 416 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 119 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 581 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

@ -1,5 +0,0 @@
<svg width="42" height="42" xmlns="http://www.w3.org/2000/svg">
<g>
<path fill="#070707" d="m6.717392,13.773912l5.6,0c2.8,0 4.7,1.9 4.7,4.7c0,2.8 -2,4.7 -4.9,4.7l-2.5,0l0,4.3l-2.9,0l0,-13.7zm2.9,2.2l0,4.9l1.9,0c1.6,0 2.6,-0.9 2.6,-2.4c0,-1.6 -0.9,-2.4 -2.6,-2.4l-1.9,0l0,-0.1zm8.9,11.5l2.7,0l0,-5.7c0,-1.4 0.8,-2.3 2.2,-2.3c0.4,0 0.8,0.1 1,0.2l0,-2.4c-0.2,-0.1 -0.5,-0.1 -0.8,-0.1c-1.2,0 -2.1,0.7 -2.4,2l-0.1,0l0,-1.9l-2.7,0l0,10.2l0.1,0zm11.7,0.1c-3.1,0 -5,-2 -5,-5.3c0,-3.3 2,-5.3 5,-5.3s5,2 5,5.3c0,3.4 -1.9,5.3 -5,5.3zm0,-2.1c1.4,0 2.2,-1.1 2.2,-3.2c0,-2 -0.8,-3.2 -2.2,-3.2c-1.4,0 -2.2,1.2 -2.2,3.2c0,2.1 0.8,3.2 2.2,3.2z" class="st0" id="Ant-Design-Pro"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 677 B

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>

Before

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -1,4 +1,5 @@
import server from '@/utils/request'
import { BASE_API_PATH } from '@/utils/variable'
export const getSsoBinds_api = (): any =>server.get(`/application/sso/me/bindings`)

View File

@ -187,6 +187,13 @@ export const getOperator = () => server.get<OperatorItem[]>('/property-calculate
*/
export const getStreamingAggType = () => server.get<Record<string, string>[]>('/dictionary/streaming-agg-type/items')
/**
*
* @pId id
* @accessId id
*/
export const getAccessConfig = (pId: string, accessId: string) => server.get(`/device-product/${pId}/${accessId}/config-metadata`)
export const getMetadataConfig = (params: {
deviceId: string;
metadata: {

View File

@ -4,6 +4,6 @@ export const restPassword = (id: string) => server.post(`/edge/operations/${id}/
export const _control = (deviceId: string) => server.get(`/edge/remote/${deviceId}/url`)
export const _stopControl = (deviceId: string) => server.get(`/edge/remote/${deviceId}/stop`, {})
export const _stopControl = (deviceId: string) => server.post(`/edge/remote/${deviceId}/stop`)

View File

@ -1,7 +1,7 @@
import server from '@/utils/request';
// 当前登录用户权限信息
export const getMe_api = () => server.get(`/authorize/me`);
export const getMe_api = () => server.get<{ user: any, [key : string]: any }>(`/authorize/me`);
// 设置登录用户选择的页面
export const setView_api = (data:object) => server.patch(`/user/settings/view/user`, data);
// 当前登录用户选择的页面

View File

@ -10,7 +10,7 @@ export const config = () => server.get(`/authorize/captcha/config`)
*
* @returns
*/
export const code = () => server.get(`/authorize/captcha/image?width=130&height=30`)
export const code = () => server.get<{ base64: string, key: string }>(`/authorize/captcha/image?width=130&height=30`)
/**
*
@ -57,3 +57,7 @@ export const userDetail = () => server.get<any>('/user/detail')
* 退
*/
export const loginout_api = () => server.get<any>('/user-token/reset')
export const getOAuth2 = (params: any) => server.get<any>('/oauth2/authorize', params)
export const initApplication = (clientId: string | number) => server.get<{name: string}>(`/application/${clientId}/info`)

View File

@ -1,5 +1,5 @@
<template>
<div class="card">
<div class="card j-table-card-box">
<div
class="card-warp"
:class="{ active: active ? 'active' : '' }"
@ -225,11 +225,13 @@ const handleClick = () => {
.card-content {
position: relative;
padding: 30px 12px 16px 30px;
padding: 30px 12px 30px 30px;
overflow: hidden;
.card-item-avatar {
margin-right: 16px;
display: flex;
align-items: center;
}
.card-item-body {
@ -237,6 +239,10 @@ const handleClick = () => {
flex-direction: column;
flex-grow: 1;
width: 0;
.ant-row{
margin-top: 19px;
}
}
.card-state {
@ -285,7 +291,7 @@ const handleClick = () => {
}
:deep(.card-item-content-text) {
color: rgba(0, 0, 0, 0.75);
color: rgba(0, 0, 0, 0.7);
font-size: 12px;
}
}

View File

@ -7,14 +7,13 @@
</template>
<script lang="ts" setup name="JEmpty">
import { Empty } from 'ant-design-vue';
import { Empty } from 'jetlinks-ui-components';
import { useSlots } from 'vue';
import NoData from './assets/nodata.svg';
import { omit } from 'lodash-es';
import type { PropType, CSSProperties } from 'vue';
const slots = useSlots();
const renderArr = Object.keys(slots);
console.log(renderArr);
const props = defineProps({
description: {

View File

@ -73,7 +73,7 @@
import { PropType } from 'vue';
import { DeleteOutlined, PlusOutlined } from '@ant-design/icons-vue';
import { useProductStore } from '@/store/product';
import { message } from 'ant-design-vue';
import { message } from 'jetlinks-ui-components';
import { useRuleEditorStore } from '@/store/ruleEditor';
import moment from 'moment';
import { getWebSocket } from '@/utils/websocket';

View File

@ -0,0 +1,27 @@
const MaxLengthStringFn = (len: number = 64) => ({
max: len,
message: `最多输入${64}个字符`,
})
export const Max_Length_64 = [MaxLengthStringFn()]
export const Max_Length_200 = [MaxLengthStringFn(200)]
export const RequiredStringFn = (name: string, type: string = 'input') => {
let typeName = '输入'
if (['select', 'date'].includes(type)) {
typeName = '选择'
}
return {
required: true,
message: `${typeName}${name}`,
}
}
export const ID_Rule = [
{
pattern: /^[a-zA-Z0-9_\-]+$/,
message: '请输入英文或者数字或者-或者_',
},
Max_Length_64[0]
]

View File

@ -1,8 +1,7 @@
<template>
<a-select v-model:value="_value" mode="tags" :options="options" :size="size" @change="change" placeholder="请选择单位"></a-select>
<j-select v-model:value="_value" mode="tags" :options="options" :size="size" @change="change" placeholder="请选择单位"></j-select>
</template>
<script setup lang="ts" name="InputSelect">
import { SizeType } from 'ant-design-vue/es/config-provider';
import { DefaultOptionType, SelectValue } from 'ant-design-vue/es/select';
import { PropType } from 'vue';
type valueType = string | number
@ -10,6 +9,8 @@ type Emits = {
(e: 'update:value', data: valueType | undefined): void;
(e: 'change'): void;
};
type SizeType = 'small' | 'middle' | 'large' | undefined;
const emit = defineEmits<Emits>();
const props = defineProps({
value: [String, Number],

View File

@ -4,6 +4,7 @@
v-model:openKeys="state.openKeys"
v-model:collapsed="state.collapsed"
v-model:selectedKeys="state.selectedKeys"
:headerHeight='60'
:pure="state.pure"
:breadcrumb="{ routes: breadcrumb }"
@backClick='routerBack'
@ -110,8 +111,6 @@ const jump = (item: any) => {
path = item.path
}
console.log(item, history.state)
console.log(path)
// jumpPage(slotProps.route.path)
router.push(path)
}
@ -119,8 +118,7 @@ const jump = (item: any) => {
const breadcrumb = computed(() =>
{
const paths = router.currentRoute.value.name as string
console.log(router.currentRoute)
console.log(route)
const metas = findRouteMeta(paths)
return metas.map((item, index) => {
return {

View File

@ -93,7 +93,7 @@ const downFile = async (type: string) => {
if (res) {
const blob = new Blob([res], { type: type });
const url = URL.createObjectURL(blob);
downloadFileByUrl(url, `设备导入模`, type);
downloadFileByUrl(url, `设备导入模`, type);
}
};

View File

@ -149,7 +149,7 @@ import {
getSearchHistory,
saveSearchHistory,
} from '@/api/comm';
import { message } from 'ant-design-vue';
import { message } from 'jetlinks-ui-components';
import LivePlayer from '@/components/Player/index.vue';
import MediaTool from '@/components/Player/mediaTool.vue';

View File

@ -7,6 +7,7 @@
:deleteRequest='deleteSearchHistory'
:columns='columns'
:class='props.class'
style='padding-top: 18px; padding-bottom: 18px;'
@search='searchSubmit'
/>
</template>

View File

@ -55,7 +55,8 @@
</template>
<script lang="ts" setup name='JProUpload'>
import { message, UploadChangeParam, UploadProps } from 'ant-design-vue';
import { UploadChangeParam, UploadProps } from 'ant-design-vue';
import { message } from 'jetlinks-ui-components';
import { FILE_UPLOAD } from '@/api/comm';
import { TOKEN_KEY } from '@/utils/variable';
import { LocalStore } from '@/utils/comm';

View File

@ -19,14 +19,16 @@ const filterPath = [ InitHomePath, AccountCenterBindPath ]
router.beforeEach((to, from, next) => {
// TODO 切换路由取消请求
const token = getToken()
if (token) {
if (to.path === AccountCenterBindPath) {
next()
} else if (token) {
if (to.path === LoginPath) {
next({ path: '/' })
} else {
const userInfo = useUserInfo()
const system = useSystem()
const menu = useMenuStore()
if (!menu.siderMenus.length && !filterPath.includes(to.path)) {
if (!Object.keys(menu.menus).length && !filterPath.includes(to.path)) {
userInfo.getUserInfo().then(() => {
system.getSystemVersion().then((menuData: any[]) => {
menuData.forEach(r => {

View File

@ -4,6 +4,7 @@ export const AccountCenterBindPath = '/account/center/bind'
export const InitLicense = '/init-license'
export const NotificationSubscriptionCode = 'account/NotificationSubscription'
export const NotificationRecordCode = 'account/NotificationRecord'
export const OauthPath = '/oauth'
export const AccountMenu = {
path: '/account',
@ -70,6 +71,13 @@ export default [
{
path: InitLicense,
component: () => import('@/views/system/License/index.vue')
},
{
path: OauthPath,
meta: {
title: '授权页'
},
component: () => import('@/views/oauth/index.vue')
}
]

View File

@ -3,6 +3,101 @@
right: -12px;
}
.ant-pro-page-container {
.ant-page-header-footer {
border-top: 1px solid #e9e9e9;
padding-top: 10px;
}
}
.ant-pro-basicLayout {
.ant-pro-top-nav-header-main {
gap: 16px;
}
.ant-pro-top-nav-header {
.ant-menu-item {
padding: 0 10px !important;
&:not(:first-child) {
margin-left: 8px;
}
&:hover {
background-color: transparent;
}
}
.ant-menu-item-selected,& .ant-menu-item-active {
transition: background 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
}
h1,& .right-content, & .anticon-bell {
color: #fff !important;
}
& .ant-pro-menu-item-title,& .anticon,& .ant-menu-item-active {
color: rgba(#fff, 0.55) !important;
}
.ant-menu-item-selected {
& .ant-pro-menu-item-title,& .anticon {
color: #fff !important;
}
}
.ant-menu-item-selected,& .ant-menu-item-active {
transition: background 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
background: linear-gradient(0deg, rgba(#fff, 0.25) 0%, rgba(#fff, 0) 82%);
&::after {
left: 0;
right: 0;
border-bottom-color: rgba(#fff, .8);
}
}
&.light {
background: #3F4960;
box-shadow: 0 1px 0px 0px #E9E9E9;
h1,& .right-content, & .anticon-bell {
color: #fff !important;
}
.ant-menu-item-selected,& .ant-menu-item-active {
transition: background 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
background: linear-gradient(0deg, rgba(#fff, 0.15) 0%, rgba(#fff, 0) 82%);
&::after {
left: 0;
right: 0;
border-bottom-color: rgba(#fff, .7);
}
}
}
}
.ant-layout-sider {
box-shadow: 1px 0 0 0 #E9E9E9 !important;
}
.ant-page-header.has-breadcrumb {
background: transparent;
padding-top: 20px;
padding-bottom: 0;
&.has-footer {
background-color: #fff;
}
}
.ant-pro-page-container-children-content {
margin-top: 16px;
}
.ant-pro-sider-menu {
padding-top: 6px;
}
}
// 说明文档样式
.doc {
height: 750px;

View File

@ -1,6 +1,6 @@
import axios from 'axios'
import { BASE_API_PATH, TOKEN_KEY } from '@/utils/variable'
import { notification as Notification } from 'ant-design-vue'
import { notification as Notification } from 'jetlinks-ui-components'
import router from '@/router'
import { LoginPath } from '@/router/menu'
import { cleanToken, getToken, LocalStore } from '@/utils/comm'
@ -13,10 +13,12 @@ interface AxiosResponseRewrite<T = any[]> extends AxiosResponse<T, any> {
export const SUCCESS_CODE = 200 // 成功代码
const filterApiUrl = ['/system/version', '/system/config/front', '/authorize/captcha/config', '/application/sso/_all', '/authorize/captcha/image', '/application/sso/bind-code', '/authorize/login']
export const request = axios.create({
withCredentials: false,
baseURL: BASE_API_PATH,
timeout: 1000 * 60 * 5
timeout: 1000 * 15
})
/**
@ -165,7 +167,8 @@ request.interceptors.request.use(config => {
// 如果 token 存在
// 让每个请求携带自定义 token 请根据实际情况自行修改
const token = getToken()
if (!token) {
const isFilterUrl = filterApiUrl.some(url => config.url.includes(url))
if (!token && !isFilterUrl) {
setTimeout(() => {
cleanToken()
router.replace({
@ -203,7 +206,7 @@ request.interceptors.response.use(response => {
}, errorHandler)
export default {
request: axios,
request,
post,
get,
patch,

View File

@ -3,13 +3,5 @@ import { isNoCommunity } from '@/utils/utils';
// 过滤网关类型
export const accessConfigTypeFilter = (data: any[], filterKey: string = 'id'): any[] => {
if (!data) return []
const filterKeys = !isNoCommunity ?
[
'mqtt-server-gateway',
'http-server-gateway',
'mqtt-client-gateway',
'tcp-server-gateway',
'plugin_gateway'
] : ['plugin_gateway']
return data.filter(item => !filterKeys.includes(item[filterKey])).map( item => ({ ...item, label: item.name, value: item.id}))
return data.map( item => ({ ...item, label: item.name, value: item.id}))
}

View File

@ -43,7 +43,7 @@
>
<template #img>
<slot name="img">
<img :src="getImage('/network.png')" />
<img :src="getImage('/channel.png')" />
</slot>
</template>
<template #content>

View File

@ -57,7 +57,7 @@
placeholder="请输入地址"
v-model:value="formData.pointKey"
:min="0"
:max="255"
:max="999999999"
:precision="0"
/>
</j-form-item>

View File

@ -621,6 +621,10 @@ const handleClick = (dt: any) => {
}
};
const handleSubscribeValue = throttle((payload: any) => {
propertyValue.value.set(payload.pointId, payload);
})
const subscribeProperty = (value: any) => {
const list = value.map((item: any) => item.id);
const id = `collector-${props.data?.channelId || 'channel'}-${
@ -635,9 +639,7 @@ const subscribeProperty = (value: any) => {
?.pipe(map((res: any) => res.payload))
.subscribe((payload: any) => {
//
throttle(() => {
propertyValue.value.set(payload.pointId, payload);
}, 1000);
handleSubscribeValue(payload)
});
};

View File

@ -55,7 +55,7 @@ export const ModBusRules = {
},
{
pattern: regOnlyNumber,
message: '请输入0-255之间的正整数',
message: '请输入0-999999999之间的正整数',
},
],
quantity: [

View File

@ -1,378 +1,417 @@
<!-- 第三方账户绑定 -->
<template>
<div class="page-container">
<div class="content">
<div class="title">第三方账户绑定</div>
<!-- 已登录-绑定三方账号 -->
<template v-if="!!token">
<div class="info">
<j-card style="width: 280px">
<template #title>
<div class="info-head">
<img :src="getImage('/bind/Rectangle.png')" />
<span>个人信息</span>
</div>
</template>
<div class="info-body">
<img
:src="
<div class='page-container'>
<div class='content'>
<div class='title'>第三方账户绑定</div>
<!-- 已登录-绑定三方账号 -->
<template v-if='!!token'>
<div class='info'>
<j-card style='width: 280px'>
<template #title>
<div class='info-head'>
<img :src="getImage('/bind/Rectangle.png')" />
<span>个人信息</span>
</div>
</template>
<div class='info-body'>
<img
:src="
user?.avatar ||
getImage('/bind/jetlinksLogo.png')
"
/>
<p>账号{{ user?.username }}</p>
<p>用户名{{ user?.name }}</p>
</div>
</j-card>
<img :src="getImage('/bind/Vector.png')" />
<j-card style="width: 280px">
<template #title>
<div class="info-head">
<img :src="getImage('/bind/Rectangle.png')" />
<span>三方账户信息</span>
</div>
</template>
<div class="info-body">
<img
:src="
/>
<p>账号{{ user?.username }}</p>
<p>用户名{{ user?.name }}</p>
</div>
</j-card>
<img :src="getImage('/bind/Vector.png')" />
<j-card style='width: 280px'>
<template #title>
<div class='info-head'>
<img :src="getImage('/bind/Rectangle.png')" />
<span>三方账户信息</span>
</div>
</template>
<div class='info-body'>
<img
:src="
iconMap.get(
bindUser?.applicationProvider,
) || getImage('/apply/provider1.png')
"
/>
<p>账号{{ bindUser?.result?.username || '-' }}</p>
<p>用户名{{ bindUser?.result?.name || '-' }}</p>
</div>
</j-card>
</div>
<div class="btn">
<j-button type="primary" @click="handleBind"
>立即绑定</j-button
>
</div>
</template>
<!-- 未登录-绑定三方账号 -->
<template v-else>
<div class="not-login">
<div class="logo">
<img :src="getImage('/bind/jetlinksLogo.png')" />
<img
class="arrow"
:src="getImage('/bind/Vector.png')"
/>
<img
:src="iconMap.get(bindUser?.applicationProvider)"
/>
</div>
<div class="desc">
你已通过
{{
bindUser?.type === 'dingtalk-ent-app'
? '钉钉'
: '微信'
}}
授权,完善以下登录信息即可以完成绑定
</div>
<div class="login-form">
<j-form layout="vertical">
<j-form-item
label="账户"
v-bind="validateInfos.username"
>
<j-input
v-model:value="formData.username"
placeholder="请输入账户"
/>
</j-form-item>
<j-form-item
label="密码"
v-bind="validateInfos.password"
>
<j-input-password
v-model:value="formData.password"
placeholder="请输入密码"
/>
</j-form-item>
<j-form-item
label="验证码"
v-bind="validateInfos.verifyCode"
>
<j-input
v-model:value="formData.verifyCode"
placeholder="请输入验证码"
>
<template #addonAfter>
<img
:src="captcha.base64"
@click="getCode"
style="cursor: pointer"
/>
</template>
</j-input>
</j-form-item>
<j-form-item>
<j-button
type="primary"
@click="handleLoginBind"
style="width: 100%"
>
登录并绑定账户
</j-button>
</j-form-item>
</j-form>
</div>
</div>
</template>
/>
<p>账号{{ bindUser?.result?.userId || '-' }}</p>
<p>用户名{{ bindUser?.result?.name || '-' }}</p>
</div>
</j-card>
</div>
<div class='btn'>
<j-button type='primary' @click='handleBind'
>立即绑定
</j-button
>
</div>
</template>
<!-- 未登录-绑定三方账号 -->
<template v-else>
<div class='not-login'>
<div class='logo'>
<img :src="getImage('/bind/jetlinksLogo.png')" />
<img
class='arrow'
:src="getImage('/bind/Vector.png')"
/>
<img
:src='iconMap.get(bindUser?.applicationProvider)'
/>
</div>
<div class='desc'>
你已通过
{{ bindUser?.appName }}
授权,完善以下登录信息即可以完成绑定
</div>
<div class='login-form'>
<j-form layout='vertical'>
<j-form-item
label='账户'
v-bind='validateInfos.username'
>
<j-input
v-model:value='formData.username'
placeholder='请输入账户'
/>
</j-form-item>
<j-form-item
label='密码'
v-bind='validateInfos.password'
>
<j-input-password
v-model:value='formData.password'
placeholder='请输入密码'
/>
</j-form-item>
<template v-if='captcha.base64'>
<j-form-item
label='验证码'
v-bind='validateInfos.verifyCode'
:rules="[
{
required: true,
message: '请输入验证码',
},
]"
>
<j-input
v-model:value='formData.verifyCode'
placeholder='请输入验证码'
>
<template #addonAfter>
<img
:src='captcha.base64'
@click='getCode'
style='cursor: pointer'
/>
</template>
</j-input>
</j-form-item>
</template>
<j-form-item>
<j-button
type='primary'
@click='handleLoginBind'
style='width: 100%'
>
登录并绑定账户
</j-button>
</j-form-item>
</j-form>
</div>
</div>
</template>
</div>
</div>
</template>
<script setup lang="ts">
import { getImage, LocalStore } from '@/utils/comm';
import { TOKEN_KEY } from '@/utils/variable';
import { Form } from 'ant-design-vue';
import { message } from 'ant-design-vue';
<script setup lang='ts' name='AccountBind'>
import { getImage, LocalStore } from '@/utils/comm'
import { TOKEN_KEY } from '@/utils/variable'
import { Form } from 'ant-design-vue'
import { message } from 'ant-design-vue'
import { applicationInfo, bindAccount } from '@/api/bind';
import { code, authLogin, userDetail } from '@/api/login';
import { applicationInfo, bindAccount } from '@/api/bind'
import { code, authLogin, userDetail } from '@/api/login'
const useForm = Form.useForm;
const useForm = Form.useForm
interface formData {
username: string;
password: string;
verifyCode: string;
username: string;
password: string;
verifyCode: string;
}
const iconMap = new Map();
iconMap.set('dingtalk-ent-app', getImage('/notice/dingtalk.png'));
iconMap.set('wechat-webapp', getImage('/notice/wechat.png'));
iconMap.set('internal-standalone', getImage('/apply/provider1.png'));
iconMap.set('third-party', getImage('/apply/provider5.png'));
const iconMap = new Map()
iconMap.set('dingtalk-ent-app', getImage('/notice/dingtalk.png'))
iconMap.set('wechat-webapp', getImage('/notice/wechat.png'))
iconMap.set('internal-standalone', getImage('/apply/provider1.png'))
iconMap.set('third-party', getImage('/apply/provider5.png'))
const token = computed(() => LocalStore.get(TOKEN_KEY));
const token = computed(() => LocalStore.get(TOKEN_KEY))
/**
* 用户信息
*/
const user = ref();
const user = ref()
const getDetail = () => {
if (!token) return;
userDetail().then((res: any) => {
user.value = res?.result;
});
};
getDetail();
if (!token.value) return
userDetail().then((res: any) => {
user.value = res?.result
})
}
/**
* 三方应用信息
*/
const bindUser = ref();
const getAppInfo = async () => {
const code = getUrlCode();
const { result } = await applicationInfo(code);
bindUser.value = result;
};
getAppInfo();
/**
* 获取url参数
*/
const getUrlCode = () => {
const url = new URLSearchParams(window.location.href);
return url.get('code') as string;
};
const url = new URLSearchParams(window.location.href)
return url.get('code') as string
}
/**
* 三方应用信息
*/
const bindUser = ref<any>({ appName: '' })
const getAppInfo = async () => {
const code = getUrlCode()
const { result } = await applicationInfo(code)
bindUser.value = result
if (result.applicationProvider === 'dingtalk-ent-app') {
bindUser.value.appName = '钉钉'
} else if (result.applicationProvider === 'wechat-webapp') {
bindUser.value.appName = '微信'
} else {
bindUser.value.appName = result.applicationName
}
}
/**
* 立即绑定
*/
const handleBind = async () => {
const code = getUrlCode();
const res = await bindAccount(code);
console.log('bindAccount: ', res);
message.success('绑定成功');
goRedirect();
setTimeout(() => window.close(), 1000);
};
const code = getUrlCode()
const res = await bindAccount(code)
console.log('bindAccount: ', res)
message.success('绑定成功')
goRedirect()
setTimeout(() => window.close(), 1000)
}
// -
const formData = ref<formData>({
username: '',
password: '',
verifyCode: '',
});
username: '',
password: '',
verifyCode: ''
})
const formRules = ref({
username: [
{
required: true,
message: '请输入账户',
},
],
password: [
{
required: true,
message: '请输入密码',
},
],
verifyCode: [
{
required: true,
message: '请输入验证码',
},
],
});
username: [
{
required: true,
message: '请输入账户'
}
],
password: [
{
required: true,
message: '请输入密码'
}
]
})
const { resetFields, validate, validateInfos } = useForm(
formData.value,
formRules.value,
);
formData.value,
formRules.value
)
/**
* 获取图形验证码
*/
const captcha = ref({
base64: '',
key: '',
});
base64: '',
key: ''
})
const getCode = async () => {
const res: any = await code();
captcha.value = res.result;
};
getCode();
const res: any = await code()
captcha.value.base64 = res.result?.base64
captcha.value.key = res.result?.key
}
/**
* 登录并绑定账户
*/
const handleLoginBind = () => {
validate()
.then(async () => {
const code = getUrlCode();
const params = {
...formData.value,
verifyKey: captcha.value.key,
bindCode: code,
expires: 3600000,
};
const res = await authLogin(params);
console.log('res: ', res);
message.success('登录成功');
goRedirect();
setTimeout(() => window.close(), 1000);
})
.catch((err) => {
getCode();
});
};
validate()
.then(async () => {
const code = getUrlCode()
const params: any = {
...formData.value,
bindCode: code,
expires: 3600000
}
if (captcha.value.base64) {
params.verifyKey = captcha.value.key
} else {
delete params.verifyCode
}
const res = await authLogin(params)
console.log('res: ', res)
if (res.success) {
message.success('登录成功')
LocalStore.set(TOKEN_KEY, res.result!.token as string)
goRedirect()
}
})
.catch((err) => {
console.log(err)
getCode()
})
}
/**
* 绑定成功跳转至页面url的: redirect
*/
const goRedirect = () => {
const urlParams = new URLSearchParams(window.location.hash);
const redirectUrl =
urlParams.get('redirect') ||
window.location.href.split('redirect=')?.[1];
console.log('redirectUrl: ', redirectUrl);
//
if (redirectUrl && redirectUrl.indexOf('account/center/bind') === -1) {
window.location.href = decodeURIComponent(redirectUrl);
}
};
const urlParams = new URLSearchParams(window.location.hash)
const redirectUrl =
urlParams.get('redirect') ||
window.location.href.split('redirect=')?.[1]
console.log('redirectUrl: ', redirectUrl)
//
if (redirectUrl && redirectUrl.indexOf('account/center/bind') === -1) {
window.location.href = decodeURIComponent(redirectUrl)
} else {
window.location.href = '/'
setTimeout(() => window.close(), 1000)
}
}
getAppInfo()
getCode()
getDetail()
</script>
<style lang="less" scoped>
<style lang='less' scoped>
:deep(
.ant-form-item-label
> label.ant-form-item-required:not(
.ant-form-item-required-mark-optional
)::before
) {
display: none;
display: none;
}
:deep(.ant-form-item-label > label) {
font-weight: bold;
font-weight: bold;
}
.page-container {
width: 100%;
height: 100vh;
background: url(/images/bind/bindPage.png) 0% 0% / 100% 100% no-repeat;
display: flex;
align-items: center;
justify-content: center;
.content {
box-sizing: border-box;
width: 850px;
min-height: 510px;
background: #fff;
border: 1px solid #e0e4e8;
border-radius: 2px;
.title {
margin: 30px 0;
color: #0f1222;
font-weight: 400;
font-size: 20px;
font-family: 'PingFang SC';
font-style: normal;
line-height: 25px;
text-align: center;
width: 100%;
height: 100vh;
background: url(/images/bind/bindPage.png) 0% 0% / 100% 100% no-repeat;
display: flex;
align-items: center;
justify-content: center;
.content {
box-sizing: border-box;
width: 850px;
min-height: 510px;
background: #fff;
border: 1px solid #e0e4e8;
border-radius: 2px;
.title {
margin: 30px 0;
color: #0f1222;
font-weight: 400;
font-size: 20px;
font-family: 'PingFang SC';
font-style: normal;
line-height: 25px;
text-align: center;
}
// -
.info {
display: flex;
align-items: center;
justify-content: center;
gap: 20px;
&-head {
display: flex;
align-items: baseline;
gap: 10px;
}
&-body {
display: flex;
flex-direction: column;
align-items: center;
gap: 10px;
img {
width: 70px;
height: 70px;
}
// -
.info {
display: flex;
align-items: center;
justify-content: center;
gap: 20px;
&-head {
display: flex;
align-items: baseline;
gap: 10px;
}
&-body {
display: flex;
flex-direction: column;
align-items: center;
gap: 10px;
img {
width: 70px;
height: 70px;
}
}
}
.btn {
display: flex;
justify-content: center;
margin-top: 30px;
}
}
.btn {
display: flex;
justify-content: center;
margin-top: 30px;
}
//
.not-login {
display: flex;
flex-direction: column;
align-items: center;
.logo {
display: flex;
align-items: center;
gap: 20px;
img {
width: 50px;
height: 50px;
}
//
.not-login {
display: flex;
flex-direction: column;
align-items: center;
.logo {
display: flex;
align-items: center;
gap: 20px;
img {
width: 50px;
height: 50px;
}
.arrow {
width: 15px;
height: 15px;
}
}
.desc {
margin-top: 30px;
margin-bottom: 30px;
font-size: 14px;
font-family: 'PingFang SC';
font-style: normal;
line-height: 14px;
opacity: 0.75;
mix-blend-mode: normal;
}
.arrow {
width: 15px;
height: 15px;
}
}
.desc {
margin-top: 30px;
margin-bottom: 30px;
font-size: 14px;
font-family: 'PingFang SC';
font-style: normal;
line-height: 14px;
opacity: 0.75;
mix-blend-mode: normal;
}
}
}
}
</style>

View File

@ -140,8 +140,10 @@
<div class="content">
<div class="account-card" v-for="item in bindList">
<img
:src="getImage(bindIcon[item.provider])"
style="height: 50px"
:src="item.logoUrl || getImage(bindIcon[item.provider])"
style="height: 50px;width: 50px"
width='50px'
height='50px'
alt=""
/>
<Ellipsis style="width: 150px; font-size: 22px">
@ -399,6 +401,8 @@ function getViews() {
display: flex;
margin-top: 24px;
flex-wrap: wrap;
gap: 24px;
.content-item {
margin-right: 24px;
@ -438,9 +442,10 @@ function getViews() {
}
.account-card {
margin-right: 24px;
width: 415px;
background-image: url(/images/notice/dingtalk-background.png);
border-right: 1px solid #f0f0f0;
border-bottom: 1px solid #f0f0f0;
display: flex;
align-items: center;
justify-content: space-between;

View File

@ -72,18 +72,16 @@ const props = defineProps({
}
.content-right {
width: 0;
height: 123px;
display: flex;
flex-grow: .7;
flex-grow: 1;
align-items: flex-end;
justify-content: flex-end;
img {
width: 100%;
height: 100%;
width: 92px;
height: 92px;
}
}
.content-right-echart{
height: 123px;
display: flex;
flex-grow: 1;
align-items: flex-end;

View File

@ -5,7 +5,7 @@
<j-col :span="6">
<TopCard
title="产品数量"
:img="getImage('/device/device-product.png')"
:img="getImage('/device/device-product.svg')"
:footer="productFooter"
:value="productTotal"
></TopCard>
@ -13,7 +13,7 @@
<j-col :span="6">
<TopCard
title="设备数量"
:img="getImage('/device/device-number.png')"
:img="getImage('/device/device-number.svg')"
:footer="deviceFooter"
:value="deviceTotal"
></TopCard
@ -53,7 +53,7 @@
</div>
</j-col>
</j-row>
<j-row :span="24" v-if="AmapKey">
<j-row :span="24" v-if="AmapKey && isNoCommunity">
<j-col :span="24">
<div class="device-position">
<Guide title="设备分布"></Guide>
@ -84,6 +84,8 @@ import { useMenuStore } from '@/store/menu';
import Amap from './components/Amap.vue';
import { useSystem } from '@/store/system';
import dayjs from 'dayjs'
import { isNoCommunity } from '@/utils/utils'
const system = useSystem();
const AmapKey = system.$state.configInfo.amap?.apiKey;
let productTotal = ref(0);
@ -605,7 +607,7 @@ getDevice();
}
.message-chart {
width: 100%;
height: 400px;
height: 470px;
}
.amap-box {
height: 500px;

View File

@ -34,7 +34,7 @@ import { TOKEN_KEY } from '@/utils/variable';
import { FIRMWARE_UPLOAD } from '@/api/device/firmware';
import { onlyMessage } from '@/utils/comm';
import type { UploadChangeParam } from 'ant-design-vue';
import { notification as Notification } from 'ant-design-vue';
import { notification as Notification } from 'jetlinks-ui-components';
import { useSystem } from '@/store/system';
const emit = defineEmits(['update:modelValue', 'update:extraValue', 'change']);

View File

@ -190,7 +190,7 @@
</j-modal>
</template>
<script lang="ts" setup>
import { message, Form } from 'ant-design-vue';
import { message, Form } from 'jetlinks-ui-components';
import { getImage } from '@/utils/comm';
import FileUpload from './FileUpload.vue';
import {

View File

@ -131,7 +131,6 @@ import {
startTask,
startOneTask,
} from '@/api/device/firmware';
import { message } from 'ant-design-vue';
import { getImage } from '@/utils/comm';
import moment from 'moment';
import { cloneDeep } from 'lodash-es';

View File

@ -108,8 +108,6 @@
</j-modal>
</template>
<script lang="ts" setup name="TaskPage">
import { message } from 'ant-design-vue';
import { getImage } from '@/utils/comm';
import { queryProduct, saveTask } from '@/api/device/firmware';
import type { FormInstance } from 'ant-design-vue';
import SelectDevices from './SelectDevices.vue';
@ -200,6 +198,7 @@ watch(
if (value.id) {
formData.value = {
...value,
mode: value.mode.value,
releaseType: value?.deviceId ? 'part' : 'all',
};
}

View File

@ -91,7 +91,7 @@
<script setup lang="ts">
import { query, bindDevice } from '@/api/device/instance';
import moment from 'moment';
import { message } from 'ant-design-vue';
import { message } from 'jetlinks-ui-components';
import { useInstanceStore } from '@/store/instance';
import { storeToRefs } from 'pinia';

View File

@ -57,7 +57,7 @@
<script lang="ts" setup>
import { treeEdgeMap, saveEdgeMap, addDevice } from '@/api/device/instance';
import { message } from 'ant-design-vue/es';
import { message } from 'jetlinks-ui-components';
const _props = defineProps({
metaData: {
type: Array,

View File

@ -132,7 +132,7 @@ import {
} from '@/api/device/instance';
import MSelect from './MSelect.vue';
import PatchMapping from './PatchMapping.vue';
import { message } from 'ant-design-vue/es';
import { message } from 'jetlinks-ui-components';
import { inject } from 'vue';
const columns = [
{

View File

@ -17,9 +17,9 @@
<j-descriptions-item label="产品名称">{{
instanceStore.current?.productName
}}</j-descriptions-item>
<j-descriptions-item label="产品分类">{{
instanceStore.current?.classifiedName
}}</j-descriptions-item>
<!-- <j-descriptions-item label="产品分类">{{-->
<!-- instanceStore.current?.classifiedName-->
<!-- }}</j-descriptions-item>-->
<j-descriptions-item label="设备类型">{{
instanceStore.current?.deviceType?.text
}}</j-descriptions-item>

View File

@ -49,7 +49,7 @@ import type { ActionsType } from '@/components/Table';
import { queryLog, queryLogsType } from '@/api/device/instance';
import { useInstanceStore } from '@/store/instance';
import moment from 'moment';
import { Modal, Textarea } from 'ant-design-vue';
import { Modal, Textarea } from 'jetlinks-ui-components';
const params = ref<Record<string, any>>({});
const instanceStore = useInstanceStore();

View File

@ -57,7 +57,7 @@
<script lang="ts" setup>
import { treeMapping, saveMapping } from '@/api/device/instance';
import { message } from 'ant-design-vue/es';
import { message } from 'jetlinks-ui-components';
const _props = defineProps({
type: {
type: String,

View File

@ -256,20 +256,20 @@ const getDetail = () => {
}
};
// watch(
// () => route.params?.id,
// async (newId) => {
// if (newId) {
// await instanceStore.refresh(String(newId));
// getStatus(String(newId));
// list.value = [...initList];
// console.log('watch', route.params?.id)
// getDetail();
// instanceStore.tabActiveKey = 'Info';
// }
// },
// { immediate: true, deep: true },
// );
const initPage = async (newId: any) => {
await instanceStore.refresh(String(newId));
getStatus(String(newId));
list.value = [...initList];
getDetail();
instanceStore.tabActiveKey = 'Info';
}
onBeforeRouteUpdate((to: any) => {
if (to.params?.id) {
initPage(to.params?.id)
}
})
const getDetailFn = async () => {
const _id = route.params?.id;
@ -286,10 +286,6 @@ onMounted(() => {
getDetailFn();
});
const onBack = () => {
menuStory.jumpPage('device/Instance');
};
const onTabChange = (e: string) => {
instanceStore.tabActiveKey = e;
};

View File

@ -164,8 +164,8 @@
>
<template #img>
<img
:width="88"
:height="88"
:width="80"
:height="80"
:src="
slotProps?.photoUrl ||
getImage('/device/instance/device-card.png')
@ -173,12 +173,12 @@
/>
</template>
<template #content>
<Ellipsis style="width: calc(100% - 100px)">
<Ellipsis style="width: calc(100% - 100px); margin-bottom: 18px;">
<span style="font-size: 16px; font-weight: 600">
{{ slotProps.name }}
</span>
</Ellipsis>
<j-row style="margin-top: 20px">
<j-row>
<j-col :span="12">
<div class="card-item-content-text">
设备类型

View File

@ -0,0 +1,315 @@
<template>
<j-modal
title="设备接入配置"
visible
width="1200px"
okText="确定"
cancelText="取消"
:confirmLoading='loading'
@ok="submitData"
@cancel="cancel"
>
<pro-search
:columns="columns"
target="deviceModal"
@search="search"
type="simple"
/>
<JProTable
:columns="columns"
:request="handleQuery"
ref="tableRef"
model="CARD"
:defaultParams="{
...temp,
sorts: accessId ? [
{ name: 'id', value: accessId },
{ name: 'createTime', order: 'desc' },
] : [{ name: 'createTime', order: 'desc' }],
}"
:params="queryParams"
@cancelSelect="cancelSelect"
:gridColumn="2"
:gridColumns="[2]"
>
<template #headerTitle>
<PermissionButton
type="primary"
@click="add"
hasPermission="link/AccessConfig:add"
>新增</PermissionButton
>
</template>
<template #deviceType="slotProps">
<div>{{ slotProps.deviceType.text }}</div>
</template>
<template #card="slotProps">
<CardBox
:value="slotProps"
@click="handleClick"
v-bind="slotProps"
:active="selectedRowKeys.includes(slotProps.id)"
:status="slotProps.state.value"
:statusText="slotProps.state.text"
:statusNames="{
enabled: 'processing',
disabled: 'error',
}"
>
<template #img>
<slot name="img">
<img :src="getImage('/device-access.png')" />
</slot>
</template>
<template #content>
<Ellipsis style="width: calc(100% - 100px)">
<h3 style="font-weight: 600">
{{ slotProps.name }}
</h3>
</Ellipsis>
<j-row>
<j-col :span="12" v-if="slotProps.channelInfo">
<div class="card-item-content-text">
{{ slotProps.channelInfo?.name }}
</div>
<Ellipsis style="width: calc(100% - 20px)">
<div>
{{
slotProps.channelInfo?.addresses
? slotProps.channelInfo
?.addresses[0].address
: ''
}}
</div>
</Ellipsis>
</j-col>
<j-col :span="12">
<div class="card-item-content-text">协议</div>
<div>{{ slotProps.protocolDetail?.name }}</div>
</j-col>
</j-row>
<j-row>
<j-col :span="24">
<Ellipsis style="width: calc(100% - 50px)"
>
<div class="context-access">
{{
getDescription(
slotProps,
)
}}
</div>
</Ellipsis
>
</j-col>
</j-row>
</template>
</CardBox>
</template>
<template #state="slotProps">
<j-badge
:text="slotProps.state.text"
:status="slotProps.state"
:statusNames='{
"enabled": "processing",
"disabled": "error",
}'
/>
</template>
<template #id="slotProps">
<a>{{ slotProps.id }}</a>
</template>
</JProTable>
</j-modal>
</template>
<script setup lang='ts' name='accessModal'>
import type { PropType } from 'vue'
import { getImage } from '@/utils/comm';
import { queryList, getAccessConfig } from '@/api/device/product'
import { message } from 'jetlinks-ui-components'
import { useMenuStore } from '@/store/menu';
type Emit = {
(e: 'submit', data: any): void
(e: 'cancel'): void
}
const props = defineProps({
productId: {
type: String,
default: undefined
},
accessId: {
type: String,
default: undefined
},
deviceType: {
type: String,
default: undefined
},
providersList: {
type: Array as PropType<any[]>,
default: () => []
}
})
const emit = defineEmits<Emit>()
const menuStore = useMenuStore();
const checkData = ref()
const tableRef = ref()
const loading = ref(false)
const params = ref<Record<string, any>>({
pageSize: 4,
terms: [],
})
const selectedRowKeys = ref<string[]>(props.accessId ? [props.accessId] : [])
const getDescription = (slotProps: Record<string, any>) =>
slotProps.description
? slotProps.description
: props.providersList?.find(
(item: Record<string, any>) => item.id === slotProps.provider,
)?.description;
/**
* 查询条件
*/
const temp = {
...params.value,
terms:
props.deviceType === 'childrenDevice'
? [
...params.value.terms,
{
terms: [
{
column: 'provider',
termType: 'in',
value: 'child-device,edge-child-device',
},
],
},
]
: [...params.value?.terms],
};
const handleQuery = async (q: any) => {
const resp = await queryList(q)
const _data = (resp.result as any)?.data as any[]
if (_data?.length) {
const _checkItem = _data.find(item => item.id === selectedRowKeys.value[0])
if (_checkItem) {
checkData.value = _checkItem
}
}
return {
...resp
}
}
const columns = [
{
title: '名称',
dataIndex: 'name',
key: 'name',
search: {
type: 'string',
},
},
{
title: '状态',
dataIndex: 'state',
key: 'state',
search: {
type: 'select',
options: [
{
label: '正常',
value: 'started',
},
{
label: '禁用',
value: 'disable',
},
],
},
},
{
title: '说明',
key: 'description',
dataIndex: 'description',
search: {
type: 'string',
},
},
]
const findProvidersByProvider = (provider: string) => {
if (!provider) return {}
return props.providersList.find(item => item.id === provider) || {}
}
/**
* 提交设备数据
*/
const submitData = async () => {
if (selectedRowKeys.value.length) {
loading.value= true
const resp = await getAccessConfig(props.productId!, checkData.value.id).catch(() => ({ success: false, result: {}}))
//
loading.value = false
if (resp.success) {
// const providers = findProvidersByProvider((resp.result as any)[0]?.provider)
emit('submit', {
access: {...checkData.value},
metadata: resp.result
})
}
} else {
message.error('请选择接入方式');
}
}
/**
* 关闭弹窗
*/
const cancel = () => {
emit('cancel')
};
const handleSearch = (e: any) => {
params.value = e;
};
const handleClick = (data: any) => {
selectedRowKeys.value = [data.id]
checkData.value = {...data}
}
const cancelSelect = () => {
selectedRowKeys.value = []
checkData.value = {}
}
/**
* 打开标签新增
*/
const add = () => {
const url = menuStore.hasMenu('link/AccessConfig/Detail');
if (url) {
const tab: any = window.open(`${origin}/#${url}?view=false`);
tab.onTabSaveSuccess = (value: any) => {
if (value.status === 200) {
tableRef.value.reload();
handleClick(value.result);
}
};
}
};
</script>
<style scoped>
</style>

View File

@ -1,6 +1,6 @@
<!-- 设备接入 -->
<template>
<div v-if="productStore.current.accessId === undefined || null">
<div v-if="access.id === undefined || null" style='margin-top: 20%; transform: translateY(-50%);'>
<j-empty :image="simpleImage">
<template #description>
<span
@ -20,42 +20,14 @@
<j-col :span="12">
<Title data="接入方式">
<template #extra>
<!-- <j-tooltip
:title="
productStore.current?.count &&
productStore.current?.count > 0
? '产品下有设备实例时不能更换接入方式'
: ''
"
>
<j-button
class="changeBtn"
size="small"
:disabled="
productStore.current?.count &&
productStore.current?.count > 0
"
ghost
type="primary"
@click="showDevice"
>更换</j-button
>
</j-tooltip> -->
<PermissionButton
style="margin: 0 0 0 20px"
type="primary"
size="small"
:tooltip="{
title:
productStore.current?.count &&
productStore.current?.count > 0
? '产品下有设备实例时不能更换接入方式'
: '',
title: tooltip
}"
:disabled="
productStore.current?.count &&
productStore.current?.count > 0
"
:disabled="checkDisabled"
ghost
@click="showDevice"
hasPermission="device/Product:update"
@ -197,7 +169,7 @@
>
<div class="info">
<div>
<div style="font-weight: 600; margin: 0 0 10 px 0">
<div style="font-weight: 600; margin: 0 0 10px 0">
{{
access?.provider === 'mqtt-server-gateway' ||
access?.provider === 'mqtt-client-gateway'
@ -214,7 +186,7 @@
:scroll="{ y: 500 }"
>
<template #bodyCell="{ text, column, record }">
<template v-if="column.key === 'topic'">
<template v-if="column?.key === 'topic'">
<j-tooltip
placement="topLeft"
:title="text"
@ -224,7 +196,7 @@
</div>
</j-tooltip>
</template>
<template v-if="column.key === 'stream'">
<template v-if="column?.key === 'stream'">
<div>{{ getStream(record) }}</div>
</template>
<template v-if="column.key === 'description'">
@ -237,7 +209,7 @@
</div>
</j-tooltip>
</template>
<template v-if="column.key === 'address'">
<template v-if="column?.key === 'address'">
<j-tooltip
placement="topLeft"
:title="text"
@ -247,7 +219,7 @@
</div>
</j-tooltip>
</template>
<template v-if="column.key === 'example'">
<template v-if="column?.key === 'example'">
<j-tooltip
placement="topLeft"
:title="text"
@ -265,133 +237,21 @@
</j-row>
</div>
<!-- 选择设备 -->
<j-modal
title="设备接入配置"
v-if="visible"
visible
width="1200px"
okText="确定"
cancelText="取消"
@ok="submitData"
@cancel="cancel"
>
<pro-search
:columns="query.columns"
target="deviceModal"
@search="search"
type="simple"
/>
<JProTable
:columns="query.columns"
:request="queryList"
ref="tableRef"
model="CARD"
:defaultParams="{
...temp,
sorts: productStore.current?.accessId ? [
{ name: 'id', value: productStore.current?.accessId },
{ name: 'createTime', order: 'desc' },
] : [{ name: 'createTime', order: 'desc' }],
}"
:params="queryParams"
@cancelSelect="cancelSelect"
:gridColumn="2"
:gridColumns="[2]"
>
<template #headerTitle>
<PermissionButton
type="primary"
@click="add"
hasPermission="link/AccessConfig:add"
>新增</PermissionButton
>
</template>
<template #deviceType="slotProps">
<div>{{ slotProps.deviceType.text }}</div>
</template>
<template #card="slotProps">
<CardBox
:value="slotProps"
@click="handleClick"
v-bind="slotProps"
:active="_selectedRowKeys.includes(slotProps.id)"
:status="slotProps.state.value"
:statusText="slotProps.state.text"
:statusNames="{
enabled: 'processing',
disabled: 'error',
}"
>
<template #img>
<slot name="img">
<img :src="getImage('/device-access.png')" />
</slot>
</template>
<template #content>
<Ellipsis style="width: calc(100% - 100px)">
<h3 style="font-weight: 600">
{{ slotProps.name }}
</h3>
</Ellipsis>
<j-row>
<j-col :span="12" v-if="slotProps.channelInfo">
<div class="card-item-content-text">
{{ slotProps.channelInfo?.name }}
</div>
<Ellipsis style="width: calc(100% - 20px)">
<div>
{{
slotProps.channelInfo?.addresses
? slotProps.channelInfo
?.addresses[0].address
: ''
}}
</div>
</Ellipsis>
</j-col>
<j-col :span="12">
<div class="card-item-content-text">协议</div>
<div>{{ slotProps.protocolDetail?.name }}</div>
</j-col>
</j-row>
<j-row>
<j-col :span="24">
<Ellipsis style="width: calc(100% - 50px)"
><div class="context-access">
{{
!!slotProps?.description
? slotProps?.description
: dataSource.find(
(item) =>
item?.id ===
slotProps?.provider,
)?.description
}}
</div></Ellipsis
>
</j-col>
</j-row>
</template>
</CardBox>
</template>
<template #state="slotProps">
<j-badge
:text="slotProps.state === 1 ? '正常' : '禁用'"
:status="statusMap.get(slotProps.state)"
/>
</template>
<template #id="slotProps">
<a>{{ slotProps.id }}</a>
</template>
</JProTable>
</j-modal>
<AccessModal
v-if='visible'
:product-id='productStore.current.id'
:deviceType='productStore.current.deviceType'
:accessId='accessId'
:providersList='dataSource'
@cancel=' visible = false'
@submit='checkAccess'
/>
</template>
<script lang="ts" setup>
<script lang="ts" setup name='AccessConfig'>
import { useProductStore } from '@/store/product';
import { ConfigMetadata } from '@/views/device/Product/typings';
import { Empty, message } from 'jetlinks-ui-components';
import { getImage } from '@/utils/comm';
import Title from '../Title/index.vue';
import { usePermissionStore } from '@/store/permission';
import { steps, steps1 } from './util';
@ -411,7 +271,7 @@ import {
detail,
modify,
} from '@/api/device/product';
import { isNoCommunity } from '@/utils/utils';
import Driver from 'driver.js';
import 'driver.js/dist/driver.min.css';
import { marked } from 'marked';
@ -419,7 +279,7 @@ import type { TableColumnType } from 'ant-design-vue';
import { useMenuStore } from '@/store/menu';
import _ from 'lodash';
import { accessConfigTypeFilter } from '@/utils/setting';
import DeviceApi from '@/api/media/device';
import AccessModal from './accessModal.vue'
const productStore = useProductStore();
const tableRef = ref();
@ -435,7 +295,8 @@ marked.setOptions({
});
const simpleImage = ref(Empty.PRESENTED_IMAGE_SIMPLE);
const visible = ref<boolean>(false);
const access = ref({});
const access = ref<Record<string, any>>({});
const accessId = ref<string>(productStore.current.accessId)
const config = ref<any>({});
const metadata = ref<ConfigMetadata>({ properties: [] });
const dataSource = ref<string[]>([]);
@ -476,115 +337,17 @@ const cancel = () => {
* 打开设备弹窗
*/
const showDevice = () => {
_selectedRowKeys.value = [productStore.current?.accessId];
visible.value = true;
};
/**
* 筛选
*/
const query = reactive({
columns: [
{
title: '名称',
dataIndex: 'name',
key: 'name',
search: {
first: true,
type: 'string',
},
},
{
title: '网关类型',
key: 'provider',
dataIndex: 'provider',
search: {
type: 'select',
options: async () => {
return new Promise((resolve) => {
getProviders().then((resp: any) => {
const data = resp.result || [];
resolve(accessConfigTypeFilter(data));
});
});
},
},
},
{
title: '状态',
key: 'state',
dataIndex: 'state',
search: {
type: 'select',
options: [
{
label: '正常',
value: 'enabled',
},
{
label: '禁用',
value: 'disabled',
},
],
},
},
{
title: '说明',
key: 'description',
dataIndex: 'description',
search: {
type: 'string',
},
},
{
title: '操作',
key: 'action',
fixed: 'right',
width: 250,
scopedSlots: true,
},
],
});
const param = ref<Record<string, any>>({
pageSize: 4,
terms: [],
});
const queryParams = ref<Record<string, any>>({});
/**
* 查询条件
*/
const temp = {
...param.value,
terms:
productStore.current?.deviceType?.value === 'childrenDevice'
? [
...param.value.terms,
{
terms: [
{
column: 'provider',
termType: 'in',
value: 'child-device,edge-child-device',
},
],
},
]
: [...param.value?.terms],
};
const _selectedRowKeys = ref<string[]>([]);
const currentForm = ref({});
const cancelSelect = () => {
_selectedRowKeys.value = [];
};
const handleClick = (dt: any) => {
_selectedRowKeys.value.splice(0, 1);
_selectedRowKeys.value = [dt.id];
current.value = {
...dt,
};
};
const search = (e: any) => {
queryParams.value = {
...e,
@ -727,6 +490,37 @@ const queryAccessDetail = async (id: string) => {
});
};
const handleColumns = () => {
const Group = {
title: '分组',
dataIndex: 'group',
key: 'group',
ellipsis: true,
align: 'center',
width: 100,
customCell: (record: any, rowIndex: number) => {
const obj = {
children: record,
rowSpan: 0,
};
const list = config.value?.routes || [];
const arr = list.filter(
(res: any) => res.group === record.group,
);
const isRowIndex =
rowIndex === 0 ||
list[rowIndex - 1].group !== record.group;
isRowIndex && (obj.rowSpan = arr.length);
return obj;
},
};
columnsMQTT.value = [Group, ...ColumnsMQTT];
columnsHTTP.value = [Group, ...ColumnsHTTP];
}
/**
* 查询协议信息
*/
@ -737,34 +531,7 @@ const getConfigDetail = (
getConfigView(messageProtocol, transportProtocol).then((resp) => {
if (resp.status === 200) {
config.value = resp.result;
const Group = {
title: '分组',
dataIndex: 'group',
key: 'group',
ellipsis: true,
align: 'center',
width: 100,
customCell: (record: any, rowIndex: number) => {
const obj = {
children: record,
rowSpan: 0,
};
const list = config.value?.routes || [];
const arr = list.filter(
(res: any) => res.group === record.group,
);
const isRowIndex =
rowIndex === 0 ||
list[rowIndex - 1].group !== record.group;
isRowIndex && (obj.rowSpan = arr.length);
return obj;
},
};
columnsMQTT.value = [Group, ...ColumnsMQTT];
columnsHTTP.value = [Group, ...ColumnsHTTP];
handleColumns()
if (config.value?.document) {
markdownToHtml.value = marked(config.value.document);
}
@ -772,101 +539,6 @@ const getConfigDetail = (
});
};
/**
* 获取网关类型
*/
const getProviderList = async () => {
const res = await getProviders().then((resp) => {
if (resp.status === 200) {
dataSource.value = resp.result;
}
});
};
/**
* 提交设备数据
*/
const submitData = async () => {
if (current.value) {
const obj: any = {
...productStore.current,
transportProtocol: current.value?.transport,
protocolName: current.value?.protocolDetail?.name,
accessId: current.value?.id,
accessName: current.value?.name,
accessProvider: current.value?.provider,
messageProtocol: current.value?.protocol,
};
// getConfigView(current.value?.protocol, current.value?.transport).then(
// (resp: any) => {
// metadata.value = (resp?.result[0] as ConfigMetadata) || {
// properties: [],
// };
// // udp
// if (metadata.value?.properties) {
// metadata.value?.properties.forEach((item) => {
// if (
// item.name === '' &&
// (!productStore.current?.configuration ||
// !productStore.current?.configuration.hasOwnProperty(
// item.name,
// ))
// ) {
// formData.data[item.name] =
// item.type.expands?.defaultValue;
// }
// });
// }
// },
// );
const metatdata = JSON.parse(productStore.current?.metadata || '{}');
if (!productStore.current?.metadata) {
const response = await getConfigView(
obj?.messageProtocol || '',
obj?.transportProtocol || '',
);
if (response.status === 200) {
const ndata = JSON.parse(response.result?.metadata || '{}');
const mdata = {
events: modifyArray(
metatdata?.events || [],
ndata?.events || [],
),
properties: modifyArray(
metatdata?.properties || [],
ndata?.properties || [],
),
functions: modifyArray(
metatdata?.functions || [],
ndata?.functions || [],
),
tags: modifyArray(metatdata?.tags || [], ndata?.tags || []),
};
// MetadataAction.insert(mdata);
obj.metadata = JSON.stringify(mdata);
}
}
// DeviceApi.getConfiguration(current.value?.protocol, current.value?.transport)
// visible.value = false;
//
const resp: any = obj.id
? await updateDevice(obj)
: await saveDevice(obj);
if (resp.status === 200) {
detail(productStore.current?.id || '').then((res) => {
if (res.status === 200) {
productStore.current = { ...res.result };
access.value = res.result;
message.success('操作成功!');
getData(obj.accessId);
}
visible.value = false;
queryParams.value = {};
});
}
} else {
message.error('请选择接入方式');
}
};
const modifyArray = (oldData: any[], newData: any[]) => {
newData.map((item) => {
if (!_.map(oldData, 'id').includes(item.id)) {
@ -894,6 +566,26 @@ const getGuide = async (isDriver1: boolean = false) => {
}
}
};
const checkAccess = async (data: any) => {
visible.value = false
accessId.value = data.access.id
access.value = data.access
metadata.value = data.metadata[0]
config.value = data.access?.transportDetail || {}
handleColumns()
markdownToHtml.value = config.value?.document ? marked(config.value.document) : '';
getGuide(!!data.metadata.length); //
}
/**
* 获取协议类型名称
*/
const getProvidersList = async () => {
const res: any = await getProviders();
dataSource.value = res.result;
};
/**
* 查询保存数据信息
*/
@ -936,12 +628,7 @@ const getData = async (accessId?: string) => {
productStore.current?.messageProtocol || '',
productStore.current?.transportProtocol || '',
);
getProviders().then((resp) => {
if (resp.status === 200) {
const data = resp.result || [];
dataSource.value = accessConfigTypeFilter(data as any[]);
}
});
}
// else {
// if (productStore.current?.id) {
@ -967,6 +654,22 @@ const submitDevice = async () => {
flatObj(values, result);
const { storePolicy, ...extra } = result;
const id = productStore.current?.id;
//TODO
// ()
const accessObj = {
...productStore.current,
transportProtocol: access.value?.transport,
protocolName: access.value?.protocolDetail?.name,
accessId: access.value?.id,
accessName: access.value?.name,
accessProvider: access.value?.provider,
messageProtocol: access.value?.protocol,
}
const updateDeviceResp = await updateDevice(accessObj)
if (!updateDeviceResp.success) return
//
const resp = await modify(id || '', {
id: id,
configuration: { ...extra },
@ -985,6 +688,7 @@ const submitDevice = async () => {
}
}
};
const flatObj = (obj: any, result: any) => {
Object.keys(obj).forEach((key: string) => {
if (typeof obj[key] === 'string') {
@ -994,20 +698,11 @@ const flatObj = (obj: any, result: any) => {
}
});
};
const getDetailInfo = () => {};
const add = () => {
const url = menuStore.hasMenu('link/AccessConfig/Detail');
if (url) {
const tab: any = window.open(`${origin}/#${url}?view=false`);
tab.onTabSaveSuccess = (value: any) => {
if (value.status === 200) {
tableRef.value.reload();
handleClick(value.result);
}
};
}
};
getProvidersList()
/**
* 初始化
*/
@ -1017,6 +712,23 @@ watchEffect(() => {
}
});
const tooltip = computed(() => {
if (productStore.current?.count > 0) {
return '产品下有设备实例时不能更换接入方式'
}
if (productStore.current.state === 1) {
return '停用产品后才可更换接入方式'
}
return ''
})
const checkDisabled = computed(() => {
if (productStore.current?.count > 0 || productStore.current.state === 1) {
return true
}
return false
})
nextTick(() => {
getData();
});

Some files were not shown because too many files have changed in this diff Show More