Quellcode durchsuchen

fix: merge next

wzyyy vor 3 Jahren
Ursprung
Commit
d727bb4a17
68 geänderte Dateien mit 1874 neuen und 573 gelöschten Zeilen
  1. BIN
      public/images/cloud/dueros-doc1.png
  2. BIN
      public/images/cloud/dueros-doc2.png
  3. BIN
      public/images/cloud/dueros-doc3.png
  4. 57 0
      public/images/device/device-number.svg
  5. 67 0
      public/images/device/device-product.svg
  6. BIN
      public/images/home/content1.png
  7. 30 0
      public/images/home/content1.svg
  8. 57 0
      public/images/home/top-1.svg
  9. 67 0
      public/images/home/top-2.svg
  10. 57 0
      public/images/media/dashboard-1.svg
  11. 62 0
      public/images/media/dashboard-2.svg
  12. 115 0
      public/images/media/dashboard-3.svg
  13. 81 0
      public/images/media/dashboard-4.svg
  14. 8 9
      src/app.tsx
  15. 4 4
      src/components/FRuleEditor/Advance/index.tsx
  16. 12 4
      src/components/Metadata/ArrayParam/index.tsx
  17. 19 18
      src/components/Metadata/JsonParam/index.tsx
  18. 20 10
      src/components/ProTableCard/CardItems/Scene/index.less
  19. 481 217
      src/components/ProTableCard/CardItems/Scene/index.tsx
  20. 1 1
      src/components/ProTableCard/index.tsx
  21. 27 0
      src/components/SearchComponent/index.less
  22. 31 10
      src/components/SearchComponent/index.tsx
  23. 6 4
      src/pages/DataCollect/Collector/components/Point/Save/modbus.tsx
  24. 6 5
      src/pages/DataCollect/Collector/components/Point/index.tsx
  25. 1 1
      src/pages/DataCollect/Collector/components/Tree/index.tsx
  26. 5 0
      src/pages/Northbound/AliCloud/Detail/index.tsx
  27. 8 7
      src/pages/Northbound/DuerOS/Detail/Doc.tsx
  28. 2 2
      src/pages/device/DashBoard/index.tsx
  29. 258 0
      src/pages/device/Firmware/Task/Save/SelectDevices.tsx
  30. 2 2
      src/pages/device/Firmware/Task/Save/index.tsx
  31. 62 39
      src/pages/device/Firmware/Task/index.tsx
  32. 21 21
      src/pages/device/Instance/Detail/Running/Property/PropertyCard.tsx
  33. 26 26
      src/pages/device/Instance/Detail/Running/Property/index.tsx
  34. 5 0
      src/pages/device/Instance/service.ts
  35. 2 3
      src/pages/device/Product/index.tsx
  36. 3 0
      src/pages/device/components/Metadata/Base/Edit/index.tsx
  37. 1 1
      src/pages/device/components/Metadata/Base/index.tsx
  38. 2 2
      src/pages/device/components/Metadata/index.tsx
  39. 1 1
      src/pages/home/components/CardStatics.tsx
  40. 1 1
      src/pages/home/components/Statistics.tsx
  41. 4 3
      src/pages/home/comprehensive/index.tsx
  42. 1 1
      src/pages/home/device/index.tsx
  43. 4 2
      src/pages/iot-card/Platform/Detail/index.tsx
  44. 28 1
      src/pages/link/AccessConfig/index.tsx
  45. 4 4
      src/pages/media/DashBoard/index.tsx
  46. 1 1
      src/pages/media/Device/Channel/service.ts
  47. 3 1
      src/pages/media/Device/Save/SaveProduct.tsx
  48. 16 4
      src/pages/media/Device/Save/index.tsx
  49. 2 2
      src/pages/media/Home/index.tsx
  50. 1 1
      src/pages/media/SplitScreen/service.ts
  51. 4 5
      src/pages/notice/Config/Detail/doc/AliyunVoice.tsx
  52. 16 20
      src/pages/notice/Config/Detail/index.tsx
  53. 119 0
      src/pages/notice/Config/Detail/regionId.ts
  54. 5 18
      src/pages/notice/Config/index.tsx
  55. 17 17
      src/pages/notice/Template/Detail/index.tsx
  56. 3 7
      src/pages/notice/Template/index.tsx
  57. 1 1
      src/pages/rule-engine/Alarm/Configuration/Save/Scene/index.tsx
  58. 1 0
      src/pages/rule-engine/Scene/Save/action/ListItem/Item.tsx
  59. 3 3
      src/pages/rule-engine/Scene/Save/action/TriggerAlarm/index.tsx
  60. 3 1
      src/pages/rule-engine/Scene/Save/action/notify/VariableDefinitions.tsx
  61. 3 7
      src/pages/rule-engine/Scene/Save/components/DatePickerFormat/index.tsx
  62. 12 5
      src/pages/rule-engine/Scene/Save/index.tsx
  63. 1 1
      src/pages/system/DataSource/Save/index.tsx
  64. 4 0
      src/pages/system/Menu/Detail/buttons.tsx
  65. 7 77
      src/pages/system/Menu/Setting/baseMenu.ts
  66. 1 1
      src/pages/system/Menu/components/permission.less
  67. 1 1
      src/pages/system/User/Save/index.tsx
  68. 1 1
      src/utils/util.ts

BIN
public/images/cloud/dueros-doc1.png


BIN
public/images/cloud/dueros-doc2.png


BIN
public/images/cloud/dueros-doc3.png


+ 57 - 0
public/images/device/device-number.svg

@@ -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>

+ 67 - 0
public/images/device/device-product.svg

@@ -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>

BIN
public/images/home/content1.png


Datei-Diff unterdrückt, da er zu groß ist
+ 30 - 0
public/images/home/content1.svg


+ 57 - 0
public/images/home/top-1.svg

@@ -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>

+ 67 - 0
public/images/home/top-2.svg

@@ -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>

+ 57 - 0
public/images/media/dashboard-1.svg

@@ -0,0 +1,57 @@
+<svg width="102" height="103" viewBox="0 0 102 103" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M5.46232 91.4268L50.8865 65.3636L96.3107 91.4268L96.3107 101.553L50.8865 127.023L5.46241 101.553L5.46232 91.4268Z" fill="white"/>
+<path d="M5.86816 92.1472L51.725 117.527V127.311L5.86816 101.931V92.1472Z" fill="url(#paint0_linear_2905_7008)"/>
+<path d="M97.0059 92.1472L51.1491 117.527V127.311L97.0059 101.931V92.1472Z" fill="#B8BFD5"/>
+<g opacity="0.7">
+<line x1="6.2959" y1="25.8047" x2="6.29589" y2="72.2964" stroke="#4980F7" stroke-opacity="0.2" stroke-width="2" stroke-dasharray="3 3"/>
+<line x1="51.25" y1="5.62109" x2="51.25" y2="41.2163" stroke="#4980F7" stroke-opacity="0.2" stroke-width="2" stroke-dasharray="3 3"/>
+<line x1="95.751" y1="25.8047" x2="95.751" y2="72.2964" stroke="#4980F7" stroke-opacity="0.2" stroke-width="2" stroke-dasharray="3 3"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M50.7275 0.542969L46.6182 4.6523L50.7275 8.76162L54.8368 4.6523L50.7275 0.542969ZM50.7274 2.59763L48.6728 4.6523L50.7274 6.70696L52.7821 4.6523L50.7274 2.59763Z" fill="#4980F7"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M95.955 23.2148L91.8457 27.3242L95.955 31.4335L100.064 27.3242L95.955 23.2148ZM95.955 25.2695L93.9003 27.3242L95.955 29.3788L98.0096 27.3242L95.955 25.2695Z" fill="#4980F7"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M5.77339 23.2148L1.66406 27.3242L5.77339 31.4335L9.88272 27.3242L5.77339 23.2148ZM5.77332 25.2695L3.71866 27.3242L5.77332 29.3788L7.82799 27.3242L5.77332 25.2695Z" fill="#4980F7"/>
+</g>
+<path d="M96.2885 92.8877V42.9454L50.8864 17.666L5.48438 42.9454V92.8877L50.8864 117.551L96.2885 92.8877Z" fill="white"/>
+<path d="M50.8864 18.2383L95.7885 43.2393V92.5903L50.8864 116.982L5.98438 92.5903V43.2393L50.8864 18.2383Z" stroke="#5995F5" stroke-opacity="0.3"/>
+<path d="M95.8802 43.0448L50.8867 17.8013V67.3349L95.8802 91.4434V43.0448Z" fill="url(#paint1_linear_2905_7008)" fill-opacity="0.1"/>
+<path opacity="0.6" d="M6.18848 92.147L50.8861 67.4263L97.0369 92.147L97.0369 92.1027L51.6127 117.574L6.18848 92.147Z" fill="url(#paint2_linear_2905_7008)"/>
+<rect x="49.751" y="18.1223" width="2.2701" height="2.2701" rx="1.13505" fill="#5995F5"/>
+<rect x="5.48438" y="42.6394" width="2.2701" height="2.2701" rx="1.13505" fill="#5995F5"/>
+<rect x="5.48438" y="90.3096" width="2.2701" height="2.2701" rx="1.13505" fill="#5995F5"/>
+<rect x="94.0176" y="42.6394" width="2.2701" height="2.2701" rx="1.13505" fill="#5995F5"/>
+<rect x="94.0176" y="90.3096" width="2.2701" height="2.2701" rx="1.13505" fill="#5995F5"/>
+<path d="M49.0716 34.875L75.1432 47.7514L49.0716 60.414L23 47.7514L49.0716 34.875Z" fill="url(#paint3_linear_2905_7008)"/>
+<path d="M75.1429 47.7551L49.0713 60.4177V97.875L75.1429 85.2124V47.7551Z" fill="url(#paint4_linear_2905_7008)"/>
+<path d="M49.0716 60.4177L23 47.7551V85.2124L49.0716 97.875V60.4177Z" fill="url(#paint5_linear_2905_7008)"/>
+<path d="M52.7959 64.2574L72.3758 54.8931V57.447L52.7959 66.8113V64.2574Z" fill="#DFE7FF"/>
+<path d="M52.7959 76.1707L72.3758 66.8064V69.3603L52.7959 78.7246V76.1707Z" fill="#DFE7FF"/>
+<path d="M52.7959 88.0975L72.3758 78.7332V81.2871L52.7959 90.6514V88.0975Z" fill="#DFE7FF"/>
+<ellipse cx="27.2268" cy="56.7264" rx="1.7026" ry="2.12825" transform="rotate(-29.2048 27.2268 56.7264)" fill="#D0DBFF"/>
+<ellipse cx="27.2268" cy="68.6397" rx="1.7026" ry="2.12825" transform="rotate(-29.2048 27.2268 68.6397)" fill="#D0DBFF"/>
+<ellipse cx="27.2268" cy="80.5531" rx="1.7026" ry="2.12825" transform="rotate(-29.2048 27.2268 80.5531)" fill="#D0DBFF"/>
+<defs>
+<linearGradient id="paint0_linear_2905_7008" x1="9.84297" y1="101.937" x2="47.6175" y2="122.278" gradientUnits="userSpaceOnUse">
+<stop stop-color="#C9D8FF"/>
+<stop offset="1" stop-color="white"/>
+</linearGradient>
+<linearGradient id="paint1_linear_2905_7008" x1="73.3834" y1="17.8013" x2="73.3834" y2="91.4434" gradientUnits="userSpaceOnUse">
+<stop offset="0.0667851" stop-color="#7A9EF4"/>
+<stop offset="1" stop-color="#EFF1F9"/>
+</linearGradient>
+<linearGradient id="paint2_linear_2905_7008" x1="28.8889" y1="69.4018" x2="74.3352" y2="114.848" gradientUnits="userSpaceOnUse">
+<stop offset="0.0001" stop-color="#A0B4FF"/>
+<stop offset="1" stop-color="#B5C4FD" stop-opacity="0.01"/>
+</linearGradient>
+<linearGradient id="paint3_linear_2905_7008" x1="49.0716" y1="34.875" x2="49.0716" y2="97.8713" gradientUnits="userSpaceOnUse">
+<stop stop-color="#C5D7FF"/>
+<stop offset="1" stop-color="#ADC6FF" stop-opacity="0"/>
+</linearGradient>
+<linearGradient id="paint4_linear_2905_7008" x1="53.5153" y1="62.6947" x2="71.2945" y2="62.8769" gradientUnits="userSpaceOnUse">
+<stop stop-color="#A0B8FF"/>
+<stop offset="0.963422" stop-color="#6A8DFF"/>
+</linearGradient>
+<linearGradient id="paint5_linear_2905_7008" x1="27.444" y1="62.6947" x2="45.2232" y2="62.8769" gradientUnits="userSpaceOnUse">
+<stop stop-color="#92B2FF"/>
+<stop offset="1" stop-color="#ADC2FE"/>
+</linearGradient>
+</defs>
+</svg>

+ 62 - 0
public/images/media/dashboard-2.svg

@@ -0,0 +1,62 @@
+<svg width="102" height="103" viewBox="0 0 102 103" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M5.46232 91.4266L50.8865 65.3634L96.3107 91.4266L96.3107 101.552L50.8865 127.023L5.46241 101.553L5.46232 91.4266Z" fill="white"/>
+<path d="M5.86816 92.147L51.725 117.527V127.311L5.86816 101.931V92.147Z" fill="url(#paint0_linear_2905_7076)"/>
+<path d="M97.0059 92.147L51.1491 117.527V127.311L97.0059 101.931V92.147Z" fill="#B8BFD5"/>
+<g opacity="0.7">
+<line x1="6.2959" y1="25.8047" x2="6.29589" y2="72.2964" stroke="#4980F7" stroke-opacity="0.2" stroke-width="2" stroke-dasharray="3 3"/>
+<line x1="51.25" y1="5.62109" x2="51.25" y2="41.2163" stroke="#4980F7" stroke-opacity="0.2" stroke-width="2" stroke-dasharray="3 3"/>
+<line x1="95.751" y1="25.8047" x2="95.751" y2="72.2964" stroke="#4980F7" stroke-opacity="0.2" stroke-width="2" stroke-dasharray="3 3"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M50.7275 0.542969L46.6182 4.6523L50.7275 8.76162L54.8368 4.6523L50.7275 0.542969ZM50.7274 2.59763L48.6728 4.6523L50.7274 6.70696L52.7821 4.6523L50.7274 2.59763Z" fill="#4980F7"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M95.955 23.2148L91.8457 27.3242L95.955 31.4335L100.064 27.3242L95.955 23.2148ZM95.955 25.2695L93.9003 27.3242L95.955 29.3788L98.0096 27.3242L95.955 25.2695Z" fill="#4980F7"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M5.77339 23.2148L1.66406 27.3242L5.77339 31.4335L9.88272 27.3242L5.77339 23.2148ZM5.77332 25.2695L3.71866 27.3242L5.77332 29.3788L7.82799 27.3242L5.77332 25.2695Z" fill="#4980F7"/>
+</g>
+<path d="M96.2885 92.8877V42.9454L50.8864 17.666L5.48438 42.9454V92.8877L50.8864 117.551L96.2885 92.8877Z" fill="white"/>
+<path d="M50.8864 18.2383L95.7885 43.2393V92.5903L50.8864 116.982L5.98438 92.5903V43.2393L50.8864 18.2383Z" stroke="#5995F5" stroke-opacity="0.3"/>
+<path d="M95.8802 43.0448L50.8867 17.8013V67.3349L95.8802 91.4434V43.0448Z" fill="url(#paint1_linear_2905_7076)" fill-opacity="0.1"/>
+<path opacity="0.6" d="M6.18848 92.147L50.8861 67.4263L97.0369 92.147L97.0369 92.1027L51.6127 117.574L6.18848 92.147Z" fill="url(#paint2_linear_2905_7076)"/>
+<rect x="49.751" y="18.1223" width="2.2701" height="2.2701" rx="1.13505" fill="#5995F5"/>
+<rect x="5.48438" y="42.6394" width="2.2701" height="2.2701" rx="1.13505" fill="#5995F5"/>
+<rect x="5.48438" y="90.3096" width="2.2701" height="2.2701" rx="1.13505" fill="#5995F5"/>
+<rect x="94.0176" y="42.6394" width="2.2701" height="2.2701" rx="1.13505" fill="#5995F5"/>
+<rect x="94.0176" y="90.3096" width="2.2701" height="2.2701" rx="1.13505" fill="#5995F5"/>
+<ellipse cx="51.0389" cy="71.5299" rx="7.79765" ry="7.93003" fill="url(#paint3_radial_2905_7076)"/>
+<path d="M41.2949 39.6127L50.8459 33.9258L60.3968 39.6127L50.8459 45.2996L41.2949 39.6127Z" fill="url(#paint4_linear_2905_7076)"/>
+<path d="M60.3976 39.6167L50.8467 45.3036L50.8467 54.1514L50.8467 65.5252L60.3976 59.8383V39.6167Z" fill="#588AFF"/>
+<path d="M50.8429 45.1647L41.292 39.4778V59.6994L50.8429 65.3863L50.8429 54.0125L50.8429 45.1647Z" fill="#8BA9FF"/>
+<path d="M18.8426 79.3315L28.4609 84.8999L35.9954 80.476L45.681 74.7891L36.0627 69.2207L18.8426 79.3315Z" fill="url(#paint5_linear_2905_7076)"/>
+<path d="M28.4609 84.9015L28.3936 96.1567L45.6136 86.0459L45.6809 74.7907L35.9954 80.4776L28.4609 84.9015Z" fill="#588AFF"/>
+<path d="M28.3936 96.1551L18.7753 90.5868L18.8426 79.3315L28.4609 84.8999L28.3936 96.1551Z" fill="#8BA9FF"/>
+<path d="M83.0421 79.3315L73.4239 84.8999L65.8894 80.476L56.2038 74.7891L65.8221 69.2207L83.0421 79.3315Z" fill="url(#paint6_linear_2905_7076)"/>
+<path d="M73.4912 96.1551L83.1095 90.5868L83.0421 79.3315L73.4239 84.8999L73.4912 96.1551Z" fill="#588AFF"/>
+<path d="M73.4239 84.9015L73.4912 96.1567L56.2711 86.0459L56.2038 74.7907L65.8894 80.4776L73.4239 84.9015Z" fill="#8BA9FF"/>
+<defs>
+<linearGradient id="paint0_linear_2905_7076" x1="9.84297" y1="101.937" x2="47.6175" y2="122.277" gradientUnits="userSpaceOnUse">
+<stop stop-color="#C9D8FF"/>
+<stop offset="1" stop-color="white"/>
+</linearGradient>
+<linearGradient id="paint1_linear_2905_7076" x1="73.3834" y1="17.8013" x2="73.3834" y2="91.4434" gradientUnits="userSpaceOnUse">
+<stop offset="0.0667851" stop-color="#7A9EF4"/>
+<stop offset="1" stop-color="#EFF1F9"/>
+</linearGradient>
+<linearGradient id="paint2_linear_2905_7076" x1="28.8889" y1="69.4018" x2="74.3352" y2="114.848" gradientUnits="userSpaceOnUse">
+<stop offset="0.0001" stop-color="#A0B4FF"/>
+<stop offset="1" stop-color="#B5C4FD" stop-opacity="0.01"/>
+</linearGradient>
+<radialGradient id="paint3_radial_2905_7076" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(46.5525 68.446) rotate(31.6324) scale(9.66012 9.66815)">
+<stop stop-color="#ADC6FF"/>
+<stop offset="1" stop-color="#5079FF"/>
+</radialGradient>
+<linearGradient id="paint4_linear_2905_7076" x1="50.8459" y1="33.9258" x2="50.8459" y2="65.5212" gradientUnits="userSpaceOnUse">
+<stop stop-color="#C5D7FF"/>
+<stop offset="1" stop-color="#DAE5FF"/>
+</linearGradient>
+<linearGradient id="paint5_linear_2905_7076" x1="18.7753" y1="90.5868" x2="45.9055" y2="75.1846" gradientUnits="userSpaceOnUse">
+<stop stop-color="#C5D7FF"/>
+<stop offset="1" stop-color="#C9D8FA"/>
+</linearGradient>
+<linearGradient id="paint6_linear_2905_7076" x1="83.1095" y1="90.5868" x2="55.9793" y2="75.1846" gradientUnits="userSpaceOnUse">
+<stop stop-color="#C5D7FF"/>
+<stop offset="1" stop-color="#C9D8FA"/>
+</linearGradient>
+</defs>
+</svg>

Datei-Diff unterdrückt, da er zu groß ist
+ 115 - 0
public/images/media/dashboard-3.svg


+ 81 - 0
public/images/media/dashboard-4.svg

@@ -0,0 +1,81 @@
+<svg width="102" height="103" viewBox="0 0 102 103" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M5.46232 91.4268L50.8865 65.3636L96.3107 91.4268L96.3107 101.553L50.8865 127.023L5.46241 101.553L5.46232 91.4268Z" fill="white"/>
+<path d="M5.86816 92.1472L51.725 117.527V127.311L5.86816 101.931V92.1472Z" fill="url(#paint0_linear_2905_7195)"/>
+<path d="M97.0059 92.1472L51.1491 117.527V127.311L97.0059 101.931V92.1472Z" fill="#B8BFD5"/>
+<g opacity="0.7">
+<line x1="6.2959" y1="25.8047" x2="6.29589" y2="72.2964" stroke="#4980F7" stroke-opacity="0.2" stroke-width="2" stroke-dasharray="3 3"/>
+<line x1="51.25" y1="5.62109" x2="51.25" y2="41.2163" stroke="#4980F7" stroke-opacity="0.2" stroke-width="2" stroke-dasharray="3 3"/>
+<line x1="95.751" y1="25.8047" x2="95.751" y2="72.2964" stroke="#4980F7" stroke-opacity="0.2" stroke-width="2" stroke-dasharray="3 3"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M50.7275 0.542969L46.6182 4.6523L50.7275 8.76162L54.8368 4.6523L50.7275 0.542969ZM50.7274 2.59763L48.6728 4.6523L50.7274 6.70696L52.7821 4.6523L50.7274 2.59763Z" fill="#4980F7"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M95.955 23.2148L91.8457 27.3242L95.955 31.4335L100.064 27.3242L95.955 23.2148ZM95.955 25.2695L93.9003 27.3242L95.955 29.3788L98.0096 27.3242L95.955 25.2695Z" fill="#4980F7"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M5.77339 23.2148L1.66406 27.3242L5.77339 31.4335L9.88272 27.3242L5.77339 23.2148ZM5.77332 25.2695L3.71866 27.3242L5.77332 29.3788L7.82799 27.3242L5.77332 25.2695Z" fill="#4980F7"/>
+</g>
+<path d="M96.2885 92.8877V42.9454L50.8864 17.666L5.48438 42.9454V92.8877L50.8864 117.551L96.2885 92.8877Z" fill="white"/>
+<path d="M50.8864 18.2383L95.7885 43.2393V92.5903L50.8864 116.982L5.98438 92.5903V43.2393L50.8864 18.2383Z" stroke="#5995F5" stroke-opacity="0.3"/>
+<path d="M95.8802 43.0448L50.8867 17.8013V67.3349L95.8802 91.4434V43.0448Z" fill="url(#paint1_linear_2905_7195)" fill-opacity="0.1"/>
+<path opacity="0.6" d="M6.18848 92.147L50.8861 67.4263L97.0369 92.147L97.0369 92.1027L51.6127 117.574L6.18848 92.147Z" fill="url(#paint2_linear_2905_7195)"/>
+<rect x="49.751" y="18.1223" width="2.2701" height="2.2701" rx="1.13505" fill="#5995F5"/>
+<rect x="5.48438" y="42.6394" width="2.2701" height="2.2701" rx="1.13505" fill="#5995F5"/>
+<rect x="5.48438" y="90.3096" width="2.2701" height="2.2701" rx="1.13505" fill="#5995F5"/>
+<rect x="94.0176" y="42.6394" width="2.2701" height="2.2701" rx="1.13505" fill="#5995F5"/>
+<rect x="94.0176" y="90.3096" width="2.2701" height="2.2701" rx="1.13505" fill="#5995F5"/>
+<path d="M71.8312 78.3524C71.8312 79.7743 71.4021 81.1386 70.6141 82.4048C67.7216 87.0531 59.9941 90.3789 50.9156 90.3789C41.8372 90.3789 34.1096 87.0531 31.2171 82.4048C30.4292 81.1386 30 79.7743 30 78.3524C30 71.7104 39.3642 66.3259 50.9156 66.3259C62.467 66.3259 71.8312 71.7104 71.8312 78.3524Z" fill="url(#paint3_linear_2905_7195)"/>
+<path d="M50.9156 98.4828C62.467 98.4828 71.8312 93.0984 71.8312 86.4564V78.3516C71.8312 79.7735 71.4021 81.1378 70.6141 82.404C67.7216 87.0522 59.9941 90.378 50.9156 90.378C41.8372 90.378 34.1096 87.0522 31.2171 82.404C30.4292 81.1378 30 79.7735 30 78.3516V86.4564C30 93.0984 39.3642 98.4828 50.9156 98.4828Z" fill="url(#paint4_linear_2905_7195)"/>
+<ellipse cx="50.6478" cy="85.7272" rx="2.18592" ry="1.98187" fill="url(#paint5_linear_2905_7195)"/>
+<ellipse cx="34.8002" cy="77.5512" rx="2.18592" ry="1.98187" fill="url(#paint6_linear_2905_7195)"/>
+<ellipse cx="66.7689" cy="77.5512" rx="2.18592" ry="1.98187" fill="url(#paint7_linear_2905_7195)"/>
+<ellipse cx="50.6478" cy="69.8715" rx="2.18592" ry="1.98187" fill="url(#paint8_linear_2905_7195)"/>
+<path d="M71.8312 48.546C71.8312 49.9679 71.4021 51.3322 70.6141 52.5984C67.7216 57.2467 59.9941 60.5725 50.9156 60.5725C41.8372 60.5725 34.1096 57.2467 31.2171 52.5984C30.4292 51.3322 30 49.9679 30 48.546C30 41.904 39.3642 36.5195 50.9156 36.5195C62.467 36.5195 71.8312 41.904 71.8312 48.546Z" fill="url(#paint9_linear_2905_7195)"/>
+<path d="M50.9156 68.6806C62.467 68.6806 71.8312 63.2962 71.8312 56.6541V48.5493C71.8312 49.9712 71.4021 51.3355 70.6141 52.6017C67.7216 57.25 59.9941 60.5758 50.9156 60.5758C41.8372 60.5758 34.1096 57.25 31.2171 52.6017C30.4292 51.3355 30 49.9712 30 48.5493V56.6541C30 63.2962 39.3642 68.6806 50.9156 68.6806Z" fill="url(#paint10_linear_2905_7195)"/>
+<path d="M60.2388 42.2703L55.4036 54.166L41.5039 45.4076L60.2388 42.2703Z" fill="url(#paint11_linear_2905_7195)"/>
+<defs>
+<linearGradient id="paint0_linear_2905_7195" x1="9.84297" y1="101.937" x2="47.6175" y2="122.278" gradientUnits="userSpaceOnUse">
+<stop stop-color="#C9D8FF"/>
+<stop offset="1" stop-color="white"/>
+</linearGradient>
+<linearGradient id="paint1_linear_2905_7195" x1="73.3834" y1="17.8013" x2="73.3834" y2="91.4434" gradientUnits="userSpaceOnUse">
+<stop offset="0.0667851" stop-color="#7A9EF4"/>
+<stop offset="1" stop-color="#EFF1F9"/>
+</linearGradient>
+<linearGradient id="paint2_linear_2905_7195" x1="28.8889" y1="69.4018" x2="74.3352" y2="114.848" gradientUnits="userSpaceOnUse">
+<stop offset="0.0001" stop-color="#A0B4FF"/>
+<stop offset="1" stop-color="#B5C4FD" stop-opacity="0.01"/>
+</linearGradient>
+<linearGradient id="paint3_linear_2905_7195" x1="50.9156" y1="64.8615" x2="50.9156" y2="97.7358" gradientUnits="userSpaceOnUse">
+<stop stop-color="#B7CDFF"/>
+<stop offset="1" stop-color="white"/>
+</linearGradient>
+<linearGradient id="paint4_linear_2905_7195" x1="37.1303" y1="84.3522" x2="65.6118" y2="85.5179" gradientUnits="userSpaceOnUse">
+<stop stop-color="#9DB7FF"/>
+<stop offset="1" stop-color="#5B8BFD"/>
+</linearGradient>
+<linearGradient id="paint5_linear_2905_7195" x1="50.6478" y1="83.5649" x2="50.6478" y2="87.6169" gradientUnits="userSpaceOnUse">
+<stop stop-color="#B0C8FF"/>
+<stop offset="1" stop-color="#88A4F4"/>
+</linearGradient>
+<linearGradient id="paint6_linear_2905_7195" x1="34.8002" y1="75.3888" x2="34.8002" y2="79.4409" gradientUnits="userSpaceOnUse">
+<stop stop-color="#B0C8FF"/>
+<stop offset="1" stop-color="#88A4F4"/>
+</linearGradient>
+<linearGradient id="paint7_linear_2905_7195" x1="66.7689" y1="75.3888" x2="66.7689" y2="79.4409" gradientUnits="userSpaceOnUse">
+<stop stop-color="#B0C8FF"/>
+<stop offset="1" stop-color="#88A4F4"/>
+</linearGradient>
+<linearGradient id="paint8_linear_2905_7195" x1="50.6478" y1="67.7091" x2="50.6478" y2="71.7612" gradientUnits="userSpaceOnUse">
+<stop stop-color="#B0C8FF"/>
+<stop offset="1" stop-color="#88A4F4"/>
+</linearGradient>
+<linearGradient id="paint9_linear_2905_7195" x1="50.9156" y1="35.0551" x2="50.9156" y2="67.9294" gradientUnits="userSpaceOnUse">
+<stop stop-color="#B7CDFF"/>
+<stop offset="1" stop-color="white"/>
+</linearGradient>
+<linearGradient id="paint10_linear_2905_7195" x1="37.1303" y1="54.55" x2="65.6118" y2="55.7157" gradientUnits="userSpaceOnUse">
+<stop stop-color="#9DB7FF"/>
+<stop offset="1" stop-color="#5B8BFD"/>
+</linearGradient>
+<linearGradient id="paint11_linear_2905_7195" x1="50.8714" y1="41.7285" x2="50.8714" y2="53.8894" gradientUnits="userSpaceOnUse">
+<stop stop-color="#B0C8FF"/>
+<stop offset="1" stop-color="#88A4F4"/>
+</linearGradient>
+</defs>
+</svg>

+ 8 - 9
src/app.tsx

@@ -15,7 +15,6 @@ import SystemConst from '@/utils/const';
 import { service as MenuService } from '@/pages/system/Menu';
 import getRoutes, {
   extraRouteArr,
-  getMenuPathByCode,
   getMenus,
   handleRoutes,
   saveMenusCache,
@@ -315,20 +314,20 @@ export const layout: RunTimeLayoutConfig = ({ initialState }) => {
       // content: initialState?.currentUser?.name,
     },
     itemRender: (route, _, routes) => {
-      const isToParentUrl = getMenuPathByCode('notice');
+      // const isToParentUrl = getMenuPathByCode('notice');
       const chilck = routes.indexOf(route) !== 0;
-      const goto = routes.some((item) => {
+      const goto = routes.some(() => {
         if (!route.path.includes('iot')) {
           return routes.indexOf(route) <= 1;
         } else {
-          if (route.path.includes('notice')) {
-            return item.path.indexOf(isToParentUrl) > -1;
-          } else {
-            return routes.indexOf(route) > 1;
-          }
+          // if (route.path.includes('notice')) {
+          //   return item.path.indexOf(isToParentUrl) > -1;
+          // } else {
+          return routes.indexOf(route) > 1;
+          // }
         }
       });
-      return chilck && goto && route.path !== '/iot/link/Channel' ? (
+      return chilck && goto ? (
         <Link to={route.path}>{route.breadcrumbName}</Link>
       ) : (
         <span>{route.breadcrumbName}</span>

+ 4 - 4
src/components/FRuleEditor/Advance/index.tsx

@@ -15,7 +15,7 @@ interface Props {
 
 const Advance = (props: Props) => {
   const { onChange, virtualRule } = props;
-  const [success, setSuccess] = useState(false);
+  const [, setSuccess] = useState(false);
   const [editorValue, setEditorValue] = useState(virtualRule.script);
   const cacheRef = useRef(virtualRule.script);
   return (
@@ -29,9 +29,9 @@ const Advance = (props: Props) => {
         Store.set('rule-editor-value', cacheRef.current);
         onChange('simple');
       }}
-      okButtonProps={{
-        disabled: !success,
-      }}
+      // okButtonProps={{
+      //   disabled: !success,
+      // }}
     >
       <div className={styles.box}>
         <div className={styles.left}>

+ 12 - 4
src/components/Metadata/ArrayParam/index.tsx

@@ -8,7 +8,11 @@ import JsonParam from '@/components/Metadata/JsonParam';
 import EnumParam from '@/components/Metadata/EnumParam';
 import BooleanEnum from '@/components/Metadata/BooleanParam';
 
-const ArrayParam = () => {
+interface Props {
+  isFunction?: boolean;
+}
+
+const ArrayParam = (props: Props) => {
   const SchemaField = createSchemaField({
     components: {
       FormItem,
@@ -82,7 +86,7 @@ const ArrayParam = () => {
               dependencies: ['.type'],
               fulfill: {
                 state: {
-                  visible: "{{['float','double'].includes($deps[0])}}",
+                  visible: !props.isFunction && "{{['float','double'].includes($deps[0])}}",
                 },
               },
             },
@@ -104,7 +108,8 @@ const ArrayParam = () => {
               dependencies: ['.type'],
               fulfill: {
                 state: {
-                  visible: "{{['int','float','long','double'].includes($deps[0])}}",
+                  visible:
+                    !props.isFunction && "{{['int','float','long','double'].includes($deps[0])}}",
                 },
               },
             },
@@ -161,7 +166,7 @@ const ArrayParam = () => {
                   dependencies: ['..type'],
                   fulfill: {
                     state: {
-                      visible: "{{['string','password'].includes($deps[0])}}",
+                      visible: !props.isFunction && "{{['string','password'].includes($deps[0])}}",
                     },
                   },
                 },
@@ -217,6 +222,9 @@ const ArrayParam = () => {
             type: 'void',
             'x-decorator': 'FormItem',
             'x-component': 'JsonParam',
+            'x-component-props': {
+              isFunction: props.isFunction,
+            },
             'x-reactions': {
               dependencies: ['.type'],
               fulfill: {

+ 19 - 18
src/components/Metadata/JsonParam/index.tsx

@@ -5,7 +5,6 @@ import { DataTypeList, DateTypeList, FileTypeList } from '@/pages/device/data';
 import { Store } from 'jetlinks-store';
 import { useAsyncDataSource } from '@/utils/util';
 import { service } from '@/pages/device/components/Metadata';
-import MetadataModel from '@/pages/device/components/Metadata/Base/model';
 import BooleanEnum from '@/components/Metadata/BooleanParam';
 import EnumParam from '@/components/Metadata/EnumParam';
 import ArrayParam from '@/components/Metadata/ArrayParam';
@@ -15,6 +14,7 @@ import Editable from '../EditTable';
 // 不算是自定义组件。只是抽离了JSONSchema
 interface Props {
   keys?: string;
+  isFunction?: boolean;
 }
 
 const JsonParam = observer((props: Props) => {
@@ -157,20 +157,11 @@ const JsonParam = observer((props: Props) => {
                       required: true,
                       'x-decorator': 'FormItem',
                       'x-component': 'Select',
-                      enum:
-                        MetadataModel.type === 'functions'
-                          ? DataTypeList.filter((item) => item.value !== 'file')
-                          : DataTypeList.filter((item) =>
-                              [
-                                'int',
-                                'long',
-                                'float',
-                                'double',
-                                'string',
-                                'boolean',
-                                'date',
-                              ].includes(item.value),
-                            ),
+                      enum: DataTypeList.filter((item) =>
+                        ['int', 'long', 'float', 'double', 'string', 'boolean', 'date'].includes(
+                          item.value,
+                        ),
+                      ),
                     },
                     booleanConfig: {
                       title: '布尔值',
@@ -210,6 +201,9 @@ const JsonParam = observer((props: Props) => {
                       }),
                       'x-decorator': 'FormItem',
                       'x-component': 'ArrayParam',
+                      'x-component-props': {
+                        isFunction: props.isFunction,
+                      },
                       'x-reactions': {
                         dependencies: ['..valueType.type'],
                         fulfill: {
@@ -255,7 +249,9 @@ const JsonParam = observer((props: Props) => {
                           dependencies: ['..valueType.type'],
                           fulfill: {
                             state: {
-                              visible: "{{['int','float','long','double'].includes($deps[0])}}",
+                              visible:
+                                !props.isFunction &&
+                                "{{['int','float','long','double'].includes($deps[0])}}",
                             },
                           },
                         },
@@ -318,7 +314,9 @@ const JsonParam = observer((props: Props) => {
                             dependencies: ['..type'],
                             fulfill: {
                               state: {
-                                visible: "{{['string','password'].includes($deps[0])}}",
+                                visible:
+                                  !props.isFunction &&
+                                  "{{['string','password'].includes($deps[0])}}",
                               },
                             },
                           },
@@ -354,7 +352,7 @@ const JsonParam = observer((props: Props) => {
                     dependencies: ['..valueType.type'],
                     fulfill: {
                       state: {
-                        visible: "{{['float','double'].includes($deps[0])}}",
+                        visible: !props.isFunction && "{{['float','double'].includes($deps[0])}}",
                       },
                     },
                   },
@@ -365,6 +363,9 @@ const JsonParam = observer((props: Props) => {
                   'x-visible': false,
                   'x-decorator': 'FormItem',
                   'x-component': 'JsonParam',
+                  'x-component-props': {
+                    isFunction: props.isFunction,
+                  },
                   'x-reactions': {
                     dependencies: ['.valueType.type'],
                     fulfill: {

+ 20 - 10
src/components/ProTableCard/CardItems/Scene/index.less

@@ -20,9 +20,12 @@
       transform: skewX(45deg);
     }
   }
+  // 卡片样式
   .card-item-content-box {
+    // 触发条件
     .card-item-content-trigger {
       display: flex;
+      overflow: hidden;
       .card-item-content-trigger-item {
         width: max-content;
         color: rgba(0, 0, 0, 0.85);
@@ -38,6 +41,7 @@
         font-size: 15px;
       }
     }
+    // 执行动作
     .card-item-content-action-item {
       display: flex;
       margin-top: 5px;
@@ -48,22 +52,20 @@
         font-weight: bold;
         font-size: 18px;
       }
+      // 执行动作
       .card-item-content-action-item-right {
-        width: calc(100% - 48px);
         padding: 5px 16px;
         border: 1px solid rgba(0, 0, 0, 0.08);
         .card-item-content-action-item-right-item {
           display: flex;
           width: 100%;
-          .trigger-contents {
-            color: rgba(0, 0, 0, 0.85);
-            font-weight: bold;
-          }
+          overflow: hidden;
+          // 触发条件 当。。。。。
           .right-item-left {
             display: flex;
             flex-direction: column;
             justify-content: center;
-            width: 15%;
+            width: max-content;
             .trigger-conditions {
               color: #fab247;
             }
@@ -71,12 +73,13 @@
               color: rgba(0, 0, 0, 0.55);
             }
           }
+          // 执行动作
           .right-item-right {
-            width: 85%;
+            width: max-content;
             .right-item-right-item {
               display: flex;
-              width: 100%;
-              overflow: hidden;
+              //overflow: hidden;
+              // 执行方式
               .trigger-ways {
                 width: 70px;
                 margin-right: 18px;
@@ -84,17 +87,22 @@
                 font-size: 16px;
                 white-space: nowrap;
               }
+              // 执行动作
               .right-item-right-item-contents {
                 display: flex;
                 align-items: center;
+                width: max-content;
                 min-width: calc(100% - 88px);
                 max-width: 100%;
+                // 执行动作内容
                 .right-item-right-item-contents-text {
                   display: flex;
+                  width: 100%;
+                  // 每个执行动作
                   .right-item-right-item-contents-item {
                     display: flex;
+                    flex-grow: 1;
                     align-items: center;
-                    width: max-content;
                     overflow: hidden;
                     white-space: nowrap;
                     text-overflow: ellipsis;
@@ -102,6 +110,7 @@
                       color: rgba(0, 0, 0, 0.85);
                       font-weight: bold;
                     }
+                    // 过滤条件
                     .right-item-right-item-contents-item-filter {
                       color: rgba(0, 0, 0, 0.65);
                     }
@@ -114,6 +123,7 @@
                     }
                   }
                 }
+                // 等***个执行动作
                 .right-item-right-item-contents-extra {
                   min-width: 100px;
                   color: #fab247;

+ 481 - 217
src/components/ProTableCard/CardItems/Scene/index.tsx

@@ -7,10 +7,11 @@ import styles from './index.less';
 import type { SceneItem } from '@/pages/rule-engine/Scene/typings';
 import { CheckOutlined, DownOutlined, UpOutlined } from '@ant-design/icons';
 import classNames from 'classnames';
-import { ActionsType, BranchesThen } from '@/pages/rule-engine/Scene/typings';
+import { ActionsType, BranchesThen, Executor } from '@/pages/rule-engine/Scene/typings';
 import MyTooltip from './MyTooltip';
 import { handleOptionsLabel } from '@/pages/rule-engine/Scene/Save/terms/paramsItem';
 import { isArray } from 'lodash';
+import TriggerAlarm from '@/pages/rule-engine/Scene/Save/action/TriggerAlarm';
 
 const imageMap = new Map();
 imageMap.set('timer', require('/public/images/scene/scene-timer.png'));
@@ -51,29 +52,99 @@ const notifyRender = (data: ActionsType | undefined) => {
   switch (data?.notify?.notifyType) {
     case 'dingTalk':
       if (data?.options?.provider === 'dingTalkRobotWebHook') {
-        return `通过群机器人消息发送${data?.options?.templateName || data?.notify?.templateId}`;
+        return (
+          <span>通过群机器人消息发送{data?.options?.templateName || data?.notify?.templateId}</span>
+        );
       }
-      return `通过钉钉向${data?.options?.notifierName || data?.notify?.notifierId}发送${
-        data?.options?.templateName || data?.notify?.templateId
-      }`;
+      return (
+        <span>
+          通过钉钉向{data?.options?.notifierName || data?.notify?.notifierId}发送
+          {data?.options?.templateName || data?.notify?.templateId}
+        </span>
+      );
     case 'weixin':
-      return `通过微信向${data?.options?.sendTo || ''}${data?.options?.orgName || ''}${
-        data?.options?.tagName || ''
-      }发送${data?.options?.templateName || data?.notify?.templateId}`;
+      return (
+        <span>
+          通过微信向{data?.options?.sendTo || ''}
+          {data?.options?.orgName || ''}
+          {data?.options?.tagName || ''}发送
+          {data?.options?.templateName || data?.notify?.templateId}
+        </span>
+      );
     case 'email':
-      return `通过邮件向${data?.options?.sendTo || ''}发送${
-        data?.options?.templateName || data?.notify?.templateId
-      }`;
+      return (
+        <span>
+          通过邮件向{data?.options?.sendTo || ''}发送
+          {data?.options?.templateName || data?.notify?.templateId}
+        </span>
+      );
     case 'voice':
-      return `通过语音向${data?.options?.sendTo || ''}发送 ${
-        data?.options?.templateName || data?.notify?.templateId
-      }`;
+      return (
+        <span>
+          通过语音向{data?.options?.sendTo || ''}发送
+          {data?.options?.templateName || data?.notify?.templateId}
+        </span>
+      );
     case 'sms':
-      return `通过短信向${data?.options?.sendTo || ''}发送${
-        data?.options?.templateName || data?.notify?.templateId
-      }`;
+      return (
+        <span>
+          通过短信向{data?.options?.sendTo || ''}发送
+          {data?.options?.templateName || data?.notify?.templateId}
+        </span>
+      );
     case 'webhook':
-      return `通过webhook发送${data?.options?.templateName || data?.notify?.templateId}`;
+      return <span>通过webhook发送{data?.options?.templateName || data?.notify?.templateId}</span>;
+    default:
+      return null;
+  }
+};
+
+const notifyTextRender = (data: ActionsType | undefined) => {
+  switch (data?.notify?.notifyType) {
+    case 'dingTalk':
+      if (data?.options?.provider === 'dingTalkRobotWebHook') {
+        return (
+          <span>通过群机器人消息发送{data?.options?.templateName || data?.notify?.templateId}</span>
+        );
+      }
+      return (
+        <span>
+          通过钉钉向{data?.options?.notifierName || data?.notify?.notifierId}发送
+          {data?.options?.templateName || data?.notify?.templateId}
+        </span>
+      );
+    case 'weixin':
+      return (
+        <span>
+          通过微信向{data?.options?.sendTo || ''}
+          {data?.options?.orgName || ''}
+          {data?.options?.tagName || ''}发送
+          {data?.options?.templateName || data?.notify?.templateId}
+        </span>
+      );
+    case 'email':
+      return (
+        <span>
+          通过邮件向{data?.options?.sendTo || ''}发送
+          {data?.options?.templateName || data?.notify?.templateId}
+        </span>
+      );
+    case 'voice':
+      return (
+        <span>
+          通过语音向{data?.options?.sendTo || ''}发送
+          {data?.options?.templateName || data?.notify?.templateId}
+        </span>
+      );
+    case 'sms':
+      return (
+        <span>
+          通过短信向{data?.options?.sendTo || ''}发送
+          {data?.options?.templateName || data?.notify?.templateId}
+        </span>
+      );
+    case 'webhook':
+      return <span>通过webhook发送{data?.options?.templateName || data?.notify?.templateId}</span>;
     default:
       return null;
   }
@@ -82,30 +153,107 @@ const notifyRender = (data: ActionsType | undefined) => {
 const deviceRender = (data: ActionsType | undefined) => {
   switch (data?.device?.selector) {
     case 'fixed':
-      return `${data?.options?.type}${data?.options?.name}${data?.options?.properties}`;
+      return (
+        <span>
+          {data?.options?.type}
+          <a
+            onClick={(e) => {
+              e.stopPropagation();
+            }}
+          >
+            {data?.options?.name}
+          </a>
+          {data?.options?.properties}
+        </span>
+      );
+    case 'tag':
+      let tags: string = '';
+      data.options?.taglist?.map((item: any) => {
+        tags += item.type || '' + item.name || '' + item.value || '';
+      });
+      return (
+        <span>
+          {data?.options?.type}
+          {tags}
+          <a
+            onClick={(e) => {
+              e.stopPropagation();
+            }}
+          >
+            {data?.options?.productName}
+          </a>
+          {data?.options?.properties}
+        </span>
+      );
+    case 'relation':
+      return (
+        <span>
+          {data?.options?.type}与
+          <a
+            onClick={(e) => {
+              e.stopPropagation();
+            }}
+          >
+            {data?.options?.triggerName}
+          </a>
+          具有相同{data?.options?.relationName}的
+          <a
+            onClick={(e) => {
+              e.stopPropagation();
+            }}
+          >
+            {data?.options?.productName}
+          </a>
+          设备的{data?.options?.properties}
+        </span>
+      );
+    default:
+      return null;
+  }
+};
+const deviceTextRender = (data: ActionsType | undefined) => {
+  switch (data?.device?.selector) {
+    case 'fixed':
+      return (
+        <span>
+          {data?.options?.type}
+          {data?.options?.name}
+          {data?.options?.properties}
+        </span>
+      );
     case 'tag':
       let tags: string = '';
       data.options?.taglist?.map((item: any) => {
         tags += item.type || '' + item.name || '' + item.value || '';
       });
-      return `${
-        data?.options?.type + tags + data?.options?.productName + data?.options?.properties
-      }`;
+      return (
+        <span>
+          {data?.options?.type}
+          {tags}
+          {data?.options?.productName}
+          {data?.options?.properties}
+        </span>
+      );
     case 'relation':
-      return `${data?.options?.type}与${data?.options?.triggerName}具有相同${data?.options?.relationName}的${data?.options?.productName}设备的${data?.options?.properties}`;
+      return (
+        <span>
+          {data?.options?.type}与{data?.options?.triggerName}具有相同{data?.options?.relationName}的
+          {data?.options?.productName}设备的{data?.options?.properties}
+        </span>
+      );
     default:
       return null;
   }
 };
 
-const actionRender = (action: ActionsType) => {
+const actionTextRender = (action: ActionsType) => {
   switch (action?.executor) {
     case 'notify':
-      return notifyRender(action);
+      return notifyTextRender(action);
     case 'delay':
       return `${action?.delay?.time}${UnitEnum[action?.delay?.unit || '']}后执行后续动作`;
     case 'device':
-      return deviceRender(action);
+      return deviceTextRender(action);
     case 'alarm':
       if (action?.alarm?.mode === 'relieve') {
         return '满足条件后将解除关联此场景的告警';
@@ -115,6 +263,58 @@ const actionRender = (action: ActionsType) => {
       return null;
   }
 };
+
+interface ActionComponentProps {
+  action: ActionsType;
+  triggerChange: (type: keyof typeof Executor) => void;
+}
+
+const ActionComponentRender = (props: ActionComponentProps) => {
+  const { action, triggerChange } = props;
+  // TODO 执行动作跳转
+  switch (action?.executor) {
+    case 'notify':
+      return notifyRender(action);
+    case 'delay':
+      return (
+        <span>{`${action?.delay?.time}${UnitEnum[action?.delay?.unit || '']}后执行后续动作`}</span>
+      );
+    case 'device':
+      return deviceRender(action);
+    case 'alarm':
+      return (
+        <span>
+          {action?.alarm?.mode === 'relieve' ? (
+            <>
+              满足条件后将解除
+              <a
+                onClick={(e) => {
+                  e.stopPropagation();
+                  triggerChange(action?.executor);
+                }}
+              >
+                关联此场景的告警
+              </a>
+            </>
+          ) : (
+            <>
+              满足条件后将触发
+              <a
+                onClick={(e) => {
+                  e.stopPropagation();
+                  triggerChange(action?.executor);
+                }}
+              >
+                关联此场景的告警
+              </a>
+            </>
+          )}
+        </span>
+      );
+    default:
+      return null;
+  }
+};
 // 过滤器
 const actionFilter = (terms: any, isLast: boolean, index: number) => {
   if (!Array.isArray(terms)) return '';
@@ -162,223 +362,259 @@ const conditionsRender = (when: any[], index: number) => {
   return whenStr;
 };
 
-const branchesActionRender = (actions: any[]) => {
+interface BranchesActionProps {
+  actions: any[];
+  triggerChange: (type: keyof typeof Executor) => void;
+}
+const BranchesActionRender = (props: BranchesActionProps) => {
+  const { actions, triggerChange } = props;
   if (actions && actions?.length) {
     const list = actions.slice(0, 3);
-    return list.map((item, index) => {
-      const isLast = index < actions.length - 1;
-      return (
-        <div
-          className={styles['right-item-right-item-contents-item']}
-          style={{ maxWidth: `(${100 / list.length})%` }}
-        >
-          <MyTooltip placement={'topLeft'} title={actionRender(item)}>
-            <div
-              className={classNames(
-                styles['right-item-right-item-contents-item-action'],
-                styles['item-ellipsis'],
-              )}
-            >
-              {actionRender(item)}
+    return (
+      <div className={classNames(styles['right-item-right-item-contents-text'])}>
+        {list.map((item, index) => {
+          const isLast = index < actions.length - 1;
+          return (
+            <div className={styles['right-item-right-item-contents-item']}>
+              <MyTooltip placement={'topLeft'} title={actionTextRender(item)}>
+                <div
+                  className={classNames(
+                    styles['right-item-right-item-contents-item-action'],
+                    styles['item-ellipsis'],
+                  )}
+                >
+                  <ActionComponentRender action={item} triggerChange={triggerChange} />
+                </div>
+              </MyTooltip>
+              <MyTooltip
+                placement={'topLeft'}
+                title={actionFilter(actions[index]?.options?.terms, isLast, index)}
+              >
+                <div
+                  className={classNames(
+                    styles['right-item-right-item-contents-item-filter'],
+                    styles['item-ellipsis'],
+                  )}
+                >
+                  {actionFilter(actions[index]?.options?.terms, isLast, index)}
+                </div>
+              </MyTooltip>
             </div>
-          </MyTooltip>
-          <MyTooltip
-            placement={'topLeft'}
-            title={actionFilter(actions[index]?.options?.terms, isLast, index)}
+          );
+        })}
+      </div>
+    );
+  } else {
+    return null;
+  }
+};
+
+const TriggerRender = (data: SceneCardProps) => {
+  const trigger = data?.options?.trigger;
+  return (
+    <div className={classNames(styles['card-item-content-trigger'])}>
+      {trigger?.name && (
+        <MyTooltip placement="topLeft" title={trigger?.name || ''}>
+          <div
+            className={classNames(styles['card-item-content-trigger-item'], 'ellipsis')}
+            style={{ maxWidth: '15%', color: 'rgba(47, 84, 235)', cursor: 'pointer' }}
+            onClick={(e) => {
+              e.stopPropagation();
+              // TODO 触发条件跳转
+              if (data.triggerType === 'device') {
+                if (data.trigger?.device?.selector === 'fixed') {
+                  // 自定义
+                  //selectorValues
+                } else if (data.trigger?.device?.selector === 'org') {
+                  // 组织
+                } else if (data.trigger?.device?.selector === 'all') {
+                  // 产品
+                }
+              }
+            }}
           >
-            <div
-              className={classNames(
-                styles['right-item-right-item-contents-item-filter'],
-                styles['item-ellipsis'],
-              )}
-            >
-              {actionFilter(actions[index]?.options?.terms, isLast, index)}
-            </div>
-          </MyTooltip>
+            {trigger?.name || ''}
+          </div>
+        </MyTooltip>
+      )}
+      {trigger?.productName && (
+        <MyTooltip placement="topLeft" title={trigger?.productName || ''}>
+          <div
+            className={classNames(styles['card-item-content-trigger-item'], 'ellipsis')}
+            style={{ maxWidth: '15%', color: 'rgba(47, 84, 235)' }}
+          >
+            {trigger?.productName || ''}
+          </div>
+        </MyTooltip>
+      )}
+      {trigger?.when && (
+        <MyTooltip placement="topLeft" title={trigger?.when || ''}>
+          <div
+            className={classNames(styles['card-item-content-trigger-item'], 'ellipsis')}
+            style={{ maxWidth: '30%' }}
+          >
+            {trigger?.when || ''}
+          </div>
+        </MyTooltip>
+      )}
+      {trigger?.time && (
+        <div className={classNames(styles['card-item-content-trigger-item'])}>
+          {trigger?.time || ''}
         </div>
-      );
-    });
-  }
-  return '';
+      )}
+      {trigger?.extraTime && (
+        <div className={classNames(styles['card-item-content-trigger-item'])}>
+          {trigger?.extraTime || ''}
+        </div>
+      )}
+      {trigger?.action && (
+        <MyTooltip placement="topLeft" title={trigger?.action || ''}>
+          <div
+            className={classNames(styles['card-item-content-trigger-item'], 'ellipsis')}
+            style={{ maxWidth: '20%' }}
+          >
+            {trigger?.action || ''}
+          </div>
+        </MyTooltip>
+      )}
+      {trigger?.type && (
+        <div className={classNames(styles['card-item-content-trigger-item'])}>
+          {trigger?.type || ''}
+        </div>
+      )}
+    </div>
+  );
 };
 
-const ContentRender = (data: SceneCardProps) => {
+export interface ActionRenderProps extends SceneCardProps {
+  triggerChange: (type: keyof typeof Executor) => void;
+}
+const ActionRender = (data: ActionRenderProps) => {
   const [visible, setVisible] = useState<boolean>(false);
   const type = data.triggerType;
 
-  if (!!type && (data.branches || [])?.length) {
-    const trigger = data?.options?.trigger;
-    return (
-      <div className={styles['card-item-content-box']}>
-        <div className={classNames(styles['card-item-content-trigger'])}>
-          {trigger?.name && (
-            <MyTooltip placement="topLeft" title={trigger?.name || ''}>
-              <div
-                className={classNames(styles['card-item-content-trigger-item'], 'ellipsis')}
-                style={{ maxWidth: '15%', color: 'rgba(47, 84, 235)' }}
-              >
-                {trigger?.name || ''}
-              </div>
-            </MyTooltip>
-          )}
-          {trigger?.productName && (
-            <MyTooltip placement="topLeft" title={trigger?.productName || ''}>
-              <div
-                className={classNames(styles['card-item-content-trigger-item'], 'ellipsis')}
-                style={{ maxWidth: '15%', color: 'rgba(47, 84, 235)' }}
-              >
-                {trigger?.productName || ''}
-              </div>
-            </MyTooltip>
-          )}
-          {trigger?.when && (
-            <MyTooltip placement="topLeft" title={trigger?.when || ''}>
-              <div
-                className={classNames(styles['card-item-content-trigger-item'], 'ellipsis')}
-                style={{ maxWidth: '16%' }}
-              >
-                {trigger?.when || ''}
-              </div>
-            </MyTooltip>
-          )}
-          {trigger?.time && (
-            <div className={classNames(styles['card-item-content-trigger-item'])}>
-              {trigger?.time || ''}
-            </div>
-          )}
-          {trigger?.extraTime && (
-            <div className={classNames(styles['card-item-content-trigger-item'])}>
-              {trigger?.extraTime || ''}
-            </div>
-          )}
-          {trigger?.action && (
-            <MyTooltip placement="topLeft" title={trigger?.action || ''}>
+  return (
+    <div className={styles['card-item-content-action']}>
+      {(visible ? data.branches || [] : (data?.branches || []).slice(0, 2)).map(
+        (item: any, index) => {
+          return (
+            <div className={styles['card-item-content-action-item']} key={item?.key || index}>
+              {type === 'device' && (
+                <div className={styles['card-item-content-action-item-left']}>
+                  {index === 0 ? '当' : '否则'}
+                </div>
+              )}
               <div
-                className={classNames(styles['card-item-content-trigger-item'], 'ellipsis')}
-                style={{ maxWidth: '15%' }}
+                style={{ width: type === 'device' ? 'calc(100% - 48px)' : '100%' }}
+                className={styles['card-item-content-action-item-right']}
               >
-                {trigger?.action || ''}
-              </div>
-            </MyTooltip>
-          )}
-          {trigger?.type && (
-            <div className={classNames(styles['card-item-content-trigger-item'])}>
-              {trigger?.type || ''}
-            </div>
-          )}
-        </div>
-        <div className={styles['card-item-content-action']}>
-          {(visible ? data.branches || [] : (data?.branches || []).slice(0, 2)).map(
-            (item: any, index) => {
-              return (
-                <div className={styles['card-item-content-action-item']} key={item?.key || index}>
-                  {type === 'device' && (
-                    <div className={styles['card-item-content-action-item-left']}>
-                      {index === 0 ? '当' : '否则'}
+                <div className={styles['card-item-content-action-item-right-item']}>
+                  {/*触发条件*/}
+                  {type === 'device' && (item.shakeLimit?.enabled || data.options?.when?.[index]) && (
+                    <div
+                      className={styles['right-item-left']}
+                      style={{
+                        maxWidth: Array.isArray(item.then) && item?.then.length ? '15%' : '100%',
+                      }}
+                    >
+                      <MyTooltip
+                        placement={'topLeft'}
+                        title={conditionsRender(data.options?.when || [], index)}
+                      >
+                        <div className={classNames(styles['trigger-conditions'], 'ellipsis')}>
+                          {conditionsRender(data.options?.when || [], index)}
+                        </div>
+                      </MyTooltip>
+                      {item.shakeLimit?.enabled && (
+                        <MyTooltip
+                          title={`(${item.shakeLimit?.time}秒内发生${item.shakeLimit?.threshold}
+                            次以上时执行一次)`}
+                        >
+                          <div className={classNames(styles['trigger-shake'], 'ellipsis')}>
+                            ({item.shakeLimit?.time}秒内发生{item.shakeLimit?.threshold}
+                            次以上时执行一次)
+                          </div>
+                        </MyTooltip>
+                      )}
                     </div>
                   )}
-                  <div
-                    style={{ width: type === 'device' ? 'calc(100% - 48px)' : '100%' }}
-                    className={styles['card-item-content-action-item-right']}
-                  >
-                    <div className={styles['card-item-content-action-item-right-item']}>
-                      {type === 'device' &&
-                        (item.shakeLimit?.enabled || data.options?.when?.[index]) && (
-                          <div
-                            className={styles['right-item-left']}
-                            style={{
-                              width: Array.isArray(item.then) && item?.then.length ? '15%' : '100%',
-                            }}
-                          >
-                            <MyTooltip
-                              placement={'topLeft'}
-                              title={conditionsRender(data.options?.when || [], index)}
-                            >
-                              <div className={classNames(styles['trigger-conditions'], 'ellipsis')}>
-                                {conditionsRender(data.options?.when || [], index)}
-                              </div>
-                            </MyTooltip>
-                            {item.shakeLimit?.enabled && (
-                              <MyTooltip
-                                title={`(${item.shakeLimit?.time}秒内发生${item.shakeLimit?.threshold}
-                            次以上时执行一次)`}
-                              >
-                                <div className={classNames(styles['trigger-shake'], 'ellipsis')}>
-                                  ({item.shakeLimit?.time}秒内发生{item.shakeLimit?.threshold}
-                                  次以上时执行一次)
+                  {/*执行动作*/}
+                  {Array.isArray(item.then) && item?.then.length ? (
+                    <div
+                      className={styles['right-item-right']}
+                      style={{ maxWidth: type === 'device' ? '85%' : '100%' }}
+                    >
+                      {(item?.then || []).map((i: BranchesThen, _index: number) => {
+                        if (Array.isArray(i?.actions) && i?.actions.length) {
+                          return (
+                            <div key={i?.key || _index} className={styles['right-item-right-item']}>
+                              {item?.then?.length > 1 && (
+                                <div className={styles['trigger-ways']}>
+                                  {i ? (i.parallel ? '并行执行' : '串行执行') : ''}
                                 </div>
-                              </MyTooltip>
-                            )}
-                          </div>
-                        )}
-                      {Array.isArray(item.then) && item?.then.length ? (
-                        <div
-                          className={styles['right-item-right']}
-                          style={{ width: type === 'device' ? '85%' : '100%' }}
-                        >
-                          {(item?.then || []).map((i: BranchesThen, _index: number) => {
-                            if (Array.isArray(i?.actions) && i?.actions.length) {
-                              return (
+                              )}
+                              {Array.isArray(i?.actions) && (
                                 <div
-                                  key={i?.key || _index}
-                                  className={styles['right-item-right-item']}
+                                  className={classNames(styles['right-item-right-item-contents'])}
                                 >
-                                  {item?.then?.length > 1 && (
-                                    <div className={styles['trigger-ways']}>
-                                      {i ? (i.parallel ? '并行执行' : '串行执行') : ''}
-                                    </div>
-                                  )}
-                                  {Array.isArray(i?.actions) && (
+                                  <div
+                                    className={classNames(
+                                      styles['right-item-right-item-contents-text'],
+                                    )}
+                                  >
+                                    <BranchesActionRender
+                                      actions={i?.actions}
+                                      triggerChange={data.triggerChange}
+                                    />
+                                  </div>
+                                  {i?.actions.length > 3 && (
                                     <div
                                       className={classNames(
-                                        styles['right-item-right-item-contents'],
+                                        styles['right-item-right-item-contents-extra'],
                                       )}
                                     >
-                                      <div
-                                        className={classNames(
-                                          styles['right-item-right-item-contents-text'],
-                                        )}
-                                      >
-                                        {branchesActionRender(i?.actions)}
-                                      </div>
-                                      {i?.actions.length > 3 && (
-                                        <div
-                                          className={classNames(
-                                            styles['right-item-right-item-contents-extra'],
-                                          )}
-                                        >
-                                          等{i?.actions.length}个执行动作
-                                        </div>
-                                      )}
+                                      等{i?.actions.length}个执行动作
                                     </div>
                                   )}
                                 </div>
-                              );
-                            }
-                            return null;
-                          })}
-                        </div>
-                      ) : (
-                        ''
-                      )}
+                              )}
+                            </div>
+                          );
+                        }
+                        return null;
+                      })}
                     </div>
-                  </div>
+                  ) : (
+                    ''
+                  )}
                 </div>
-              );
-            },
-          )}
-          {(data?.branches || []).length > 2 && (
-            <div
-              className={styles['trigger-actions-more']}
-              onClick={(e) => {
-                e.stopPropagation();
-                setVisible(!visible);
-              }}
-            >
-              展开更多{!visible ? <DownOutlined /> : <UpOutlined />}
+              </div>
             </div>
-          )}
+          );
+        },
+      )}
+      {(data?.branches || []).length > 2 && (
+        <div
+          className={styles['trigger-actions-more']}
+          onClick={(e) => {
+            e.stopPropagation();
+            setVisible(!visible);
+          }}
+        >
+          展开更多{!visible ? <DownOutlined /> : <UpOutlined />}
         </div>
+      )}
+    </div>
+  );
+};
+
+const ContentRender = (data: ActionRenderProps) => {
+  const type = data.triggerType;
+  if (!!type && (data.branches || [])?.length) {
+    return (
+      <div className={styles['card-item-content-box']}>
+        <TriggerRender {...data} />
+        <ActionRender {...data} triggerChange={data.triggerChange} />
       </div>
     );
   } else {
@@ -387,6 +623,7 @@ const ContentRender = (data: SceneCardProps) => {
 };
 
 export const ExtraSceneCard = (props: SceneCardProps) => {
+  const [triggerVisible, setTriggerVisible] = useState<boolean>(false);
   return (
     <TableCard
       status={props.state.value}
@@ -422,7 +659,12 @@ export const ExtraSceneCard = (props: SceneCardProps) => {
               />
             </div>
           </div>
-          <ContentRender {...props} />
+          <ContentRender
+            {...props}
+            triggerChange={() => {
+              setTriggerVisible(true);
+            }}
+          />
         </div>
       </div>
       <div className={styles['card-item-trigger-type']}>
@@ -436,11 +678,20 @@ export const ExtraSceneCard = (props: SceneCardProps) => {
           <CheckOutlined />
         </div>
       </div>
+      {triggerVisible && (
+        <TriggerAlarm
+          id={props.id}
+          close={() => {
+            setTriggerVisible(false);
+          }}
+        />
+      )}
     </TableCard>
   );
 };
 
 export default (props: SceneCardProps) => {
+  const [triggerVisible, setTriggerVisible] = useState<boolean>(false);
   return (
     <TableCard
       showMask={false}
@@ -475,7 +726,12 @@ export default (props: SceneCardProps) => {
               />
             </div>
           </div>
-          <ContentRender {...props} />
+          <ContentRender
+            {...props}
+            triggerChange={() => {
+              setTriggerVisible(true);
+            }}
+          />
         </div>
       </div>
       <div className={styles['card-item-trigger-type']}>
@@ -484,6 +740,14 @@ export default (props: SceneCardProps) => {
           {TriggerWayType[props.triggerType]}
         </div>
       </div>
+      {triggerVisible && (
+        <TriggerAlarm
+          id={props.id}
+          close={() => {
+            setTriggerVisible(false);
+          }}
+        />
+      )}
     </TableCard>
   );
 };

+ 1 - 1
src/components/ProTableCard/index.tsx

@@ -329,7 +329,7 @@ const ProTableCard = <
                     ? num / pageSize - 1
                     : parseInt(num / pageSize);
                 const min = minSize > num ? pageIndexInt * pageSize + 1 : minSize;
-
+                if (min === 1) pageChange(min, pageSize);
                 return `第 ${min} - ${max} 条/总共 ${num} 条`;
               }}
             />

+ 27 - 0
src/components/SearchComponent/index.less

@@ -26,6 +26,19 @@
       }
     }
   }
+  .small-action {
+    gap: 48px;
+    justify-content: flex-start;
+    width: 100%;
+
+    .more {
+      position: relative;
+    }
+
+    .advance {
+      right: 0;
+    }
+  }
 
   .form {
     :global {
@@ -51,6 +64,20 @@
     }
   }
 
+  .small-size {
+    flex-wrap: wrap;
+    :global {
+      .ant-formily-grid-layout {
+        grid-template-columns: repeat(12, minmax(0, 1fr)) !important;
+        width: 100%;
+      }
+      .ant-formily-item {
+        width: 100%;
+        margin-bottom: 24px;
+      }
+    }
+  }
+
   .history {
     width: 176px;
   }

+ 31 - 10
src/components/SearchComponent/index.tsx

@@ -36,6 +36,7 @@ import classnames from 'classnames';
 import { onlyMessage, randomString } from '@/utils/util';
 import { useHistory, useLocation } from 'umi';
 import { Empty } from '@/components';
+import { useSize } from 'ahooks';
 
 const ui2Server = (source: SearchTermsUI): SearchTermsServer => [
   { terms: source.terms1 },
@@ -195,6 +196,8 @@ const SearchComponent = <T extends Record<string, any>>(props: Props<T>) => {
   const [history, setHistory] = useState([]);
   const [logVisible, setLogVisible] = useState<boolean>(false);
   const uiParamRef = useRef(initParam);
+  const formDivRef = useRef(null);
+  const formDivSize = useSize(formDivRef);
 
   const form = useMemo(
     () =>
@@ -601,6 +604,9 @@ const SearchComponent = <T extends Record<string, any>>(props: Props<T>) => {
       // 展开高级搜索
       setExpand(false);
       handleForm(true);
+    } else {
+      setExpand(true);
+      handleForm(false);
     }
     const params = new URLSearchParams(_location.search);
     params.delete('q');
@@ -663,15 +669,17 @@ const SearchComponent = <T extends Record<string, any>>(props: Props<T>) => {
     <Menu className={styles.history}>
       {history.length > 0 ? (
         history.map((item: SearchHistory) => (
-          <Menu.Item
-            key={item.id || randomString(9)}
-            onClick={() => {
-              handleHistory(item);
-              handleSearch();
-            }}
-          >
+          <Menu.Item key={item.id || randomString(9)}>
             <div className={styles.list}>
-              <Typography.Text className={styles['list-text']} ellipsis={{ tooltip: item.name }}>
+              <Typography.Text
+                className={styles['list-text']}
+                ellipsis={{ tooltip: item.name }}
+                onClick={(e) => {
+                  e.stopPropagation();
+                  handleHistory(item);
+                  handleSearch();
+                }}
+              >
                 {item.name}
               </Typography.Text>
               <Popconfirm
@@ -835,9 +843,22 @@ const SearchComponent = <T extends Record<string, any>>(props: Props<T>) => {
         wrapperCol={18}
         onAutoSubmit={() => (SearchBtn.advance ? handleSearch : handleSearch(false))}
       >
-        <div className={expand && styles.simple}>
+        <div
+          className={classnames({
+            [styles.simple]: expand,
+            [styles['small-size']]:
+              formDivSize?.width && expand && model !== 'simple' && formDivSize.width < 1000,
+          })}
+          ref={formDivRef}
+        >
           <SchemaField schema={expand ? simpleSchema : schema} />
-          <div className={styles.action} style={{ marginTop: expand ? 0 : -12 }}>
+          <div
+            className={classnames(styles.action, {
+              [styles['small-action']]:
+                formDivSize?.width && expand && model !== 'simple' && formDivSize.width < 1000,
+            })}
+            style={{ marginTop: expand ? 0 : -12 }}
+          >
             <Space>
               {enableSave ? SearchBtn.advance : SearchBtn.simple}
               {enableSave && SaveBtn}

+ 6 - 4
src/pages/DataCollect/Collector/components/Point/Save/modbus.tsx

@@ -81,10 +81,12 @@ export default (props: Props) => {
     field.loading = true;
     services(field).then(
       action.bound!((resp: any) => {
-        field.dataSource = (resp?.result || []).map((item: any) => ({
-          label: item.name,
-          value: item.id,
-        }));
+        field.dataSource = (resp?.result || [])
+          .filter((i: any) => i?.id !== 'property')
+          .map((item: any) => ({
+            label: item.name,
+            value: item.id,
+          }));
         field.loading = false;
       }),
     );

+ 6 - 5
src/pages/DataCollect/Collector/components/Point/index.tsx

@@ -236,10 +236,10 @@ const PointCard = observer((props: PointCardProps) => {
         loading={loading}
         bordered={false}
         className={'data-collect-point'}
-        style={{ position: 'relative', minHeight: 600 }}
+        style={{ position: 'relative', overflowY: 'auto' }}
         bodyStyle={{ paddingTop: 4 }}
       >
-        <div>
+        <div style={{ height: 620 }}>
           <div style={{ height: '100%', paddingBottom: 48 }}>
             {props.data?.id !== '*' && props.data?.id && (
               <div style={{ width: '100%', display: 'flex', justifyContent: 'flex-start' }}>
@@ -345,10 +345,11 @@ const PointCard = observer((props: PointCardProps) => {
                   style={{
                     display: 'flex',
                     justifyContent: 'flex-end',
-                    position: 'absolute',
+                    // position: 'absolute',
                     width: '100%',
-                    bottom: 10,
-                    right: '2%',
+                    // bottom: 10,
+                    // right: '2%',
+                    marginTop: 20,
                   }}
                 >
                   <Pagination

+ 1 - 1
src/pages/DataCollect/Collector/components/Tree/index.tsx

@@ -154,7 +154,7 @@ export default observer((props: Props) => {
             style={{ overflow: 'hidden' }}
             className={styles['data-collect-tree']}
             showIcon
-            height={500}
+            height={document.body.clientHeight < 1000 ? document.body.clientHeight * 0.7 : 650}
             selectedKeys={TreeModel.selectedKeys}
             defaultExpandAll
             autoExpandParent

+ 5 - 0
src/pages/Northbound/AliCloud/Detail/index.tsx

@@ -431,7 +431,12 @@ const Detail = observer(() => {
         document.title = '阿里云';
       }
     }, 0);
+    return () => {
+      Store.set('datalist', []);
+      Store.set('productList', []);
+    };
   }, []);
+
   useEffect(() => {
     if (location && location.state) {
       setView(location.state.view);

+ 8 - 7
src/pages/Northbound/DuerOS/Detail/Doc.tsx

@@ -1,5 +1,6 @@
-import { InfoCircleFilled } from '@ant-design/icons';
-import { Alert, Image } from 'antd';
+// import { InfoCircleFilled } from '@ant-design/icons';
+// import { Alert, Image } from 'antd';
+import { Image } from 'antd';
 
 const image = require('/public/images/cloud/dueros-doc.jpg');
 const image1 = require('/public/images/cloud/dueros-doc1.png');
@@ -33,26 +34,26 @@ const Doc = () => {
         <div>物联网平台的登录地址。注意需要为https。</div>
         <div>请复制并填写: https://{location.host}/#/user/login</div>
         <h1>Client_Id</h1>
-        <div>请填写物联网平台-第三方平台的clientId。</div>
+        <div>请填写系统管理-应用管理中的clientId。</div>
         <div className={'image'}>
           <Image width="100%" src={image1} />
         </div>
         <h1>回调地址</h1>
-        <div>请复制DuerOS平台中的值,填写到第三方平台-redirectUrl中</div>
-        <div>
+        <div>请复制DuerOS平台中的值,填写到系统管理-应用管理中-redirectUrl中。</div>
+        {/* <div>
           <Alert
             icon={<InfoCircleFilled style={{ fontSize: 16, marginTop: 5 }} />}
             description="注:需要将OAth2设置为开启状态。"
             showIcon
           />
-        </div>
+        </div> */}
         <div className={'image'}>
           <Image width="100%" src={image2} />
         </div>
         <h1>Token地址</h1>
         <div>请复制并填写:HTTPS://{location.host}/api/v1/token</div>
         <h1>ClientSecret</h1>
-        <div>请复制物联网平台-第三方平台中的secureKey,填写到DuerOS平台。</div>
+        <div>请复制系统管理-应用管理中的secureKey,填写到DuerOS平台。</div>
         <div className={'image'}>
           <Image width="100%" src={image3} />
         </div>

+ 2 - 2
src/pages/device/DashBoard/index.tsx

@@ -397,7 +397,7 @@ const DeviceBoard = () => {
             ]}
             span={6}
           >
-            <img src={require('/public/images/device/device-product.png')} />
+            <img src={require('/public/images/device/device-product.svg')} />
           </DashBoardTopCard.Item>
           <DashBoardTopCard.Item
             title={'设备数量'}
@@ -416,7 +416,7 @@ const DeviceBoard = () => {
             ]}
             span={6}
           >
-            <img src={require('/public/images/device/device-number.png')} />
+            <img src={require('/public/images/device/device-number.svg')} />
           </DashBoardTopCard.Item>
           <DashBoardTopCard.Item
             title={'当前在线'}

+ 258 - 0
src/pages/device/Firmware/Task/Save/SelectDevices.tsx

@@ -0,0 +1,258 @@
+import { Badge, Checkbox, Input, Modal } from 'antd';
+import { EditOutlined } from '@ant-design/icons';
+import type { Key } from 'react';
+import { useEffect, useRef } from 'react';
+import type { ActionType, ProColumns } from '@jetlinks/pro-table';
+import ProTable from '@jetlinks/pro-table';
+import type { DeviceInstance } from '@/pages/device/Instance/typings';
+import { useIntl } from '@@/plugin-locale/localeExports';
+import Service from '@/pages/device/Instance/service';
+import { observer } from '@formily/react';
+import { model } from '@formily/reactive';
+import moment from 'moment';
+import SearchComponent from '@/components/SearchComponent';
+
+interface Props {
+  id?: string;
+  value?: Partial<DeviceInstance>[];
+  onChange?: (data: Partial<DeviceInstance>[]) => void;
+  productId?: string;
+  disabled?: boolean;
+}
+
+const deviceStatus = new Map();
+deviceStatus.set('online', <Badge status="success" text={'在线'} />);
+deviceStatus.set('offline', <Badge status="error" text={'离线'} />);
+deviceStatus.set('notActive', <Badge status="processing" text={'禁用'} />);
+
+const service = new Service('device/instance');
+const State = model<{
+  visible: boolean;
+  data: Partial<DeviceInstance>[];
+  dataList: Partial<DeviceInstance>[];
+  searchParam: any;
+}>({
+  visible: false,
+  data: [],
+  dataList: [],
+  searchParam: { terms: [] },
+});
+
+const SelectDevices = observer((props: Props) => {
+  const intl = useIntl();
+  const actionRef1 = useRef<ActionType>();
+  // const [searchParam, setSearchParam] = useState<any>({terms: []});
+  const columns: ProColumns<DeviceInstance>[] = [
+    {
+      title: 'ID',
+      dataIndex: 'id',
+      ellipsis: true,
+    },
+    {
+      title: intl.formatMessage({
+        id: 'pages.table.deviceName',
+        defaultMessage: '设备名称',
+      }),
+      dataIndex: 'name',
+      ellipsis: true,
+    },
+    {
+      title: '固件版本',
+      dataIndex: 'firmwareInfo',
+      ellipsis: true,
+      render: (text: any, record: any) => record?.version || '',
+    },
+    {
+      title: intl.formatMessage({
+        id: 'pages.device.instance.registrationTime',
+        defaultMessage: '注册时间',
+      }),
+      dataIndex: 'registryTime',
+      width: '200px',
+      valueType: 'dateTime',
+      render: (text: any, record: any) =>
+        record?.registerTime ? moment(record?.registerTime).format('YYYY-MM-DD HH:mm:ss') : '',
+    },
+    {
+      title: '状态',
+      dataIndex: 'state',
+      render: (text: any, record: any) =>
+        record?.state?.value ? deviceStatus.get(record?.state?.value) : '',
+      ellipsis: true,
+    },
+  ];
+
+  // const [data, setData] = useState<Partial<DeviceInstance>[]>(props?.value || []);
+  // const [dataList, setDataList] = useState<Partial<DeviceInstance>[]>(props?.value || []);
+
+  const rowSelection = {
+    onSelect: (selectedRow: any, selected: any) => {
+      let newSelectKeys = [...State.data];
+      if (selected) {
+        newSelectKeys.push({ ...selectedRow });
+      } else {
+        newSelectKeys = newSelectKeys.filter((item) => item.id !== selectedRow.id);
+      }
+      State.data = newSelectKeys;
+    },
+    onSelectAll: (selected: boolean, _: any, changeRows: any) => {
+      let newSelectKeys = [...State.data];
+      if (selected) {
+        changeRows.forEach((item: any) => {
+          newSelectKeys.push({ ...item });
+        });
+      } else {
+        newSelectKeys = newSelectKeys.filter((a) => {
+          return !changeRows.some((b: any) => b.id === a.id);
+        });
+      }
+      State.data = newSelectKeys;
+    },
+    selectedRowKeys: State.data?.map((item) => item.id) as Key[],
+  };
+
+  const CheckAllData = () => {
+    service
+      .queryDetailListNoPaging({
+        context: {
+          includeTags: false,
+          includeBind: false,
+          includeRelations: false,
+        },
+        ...State.searchParam,
+        terms: [
+          ...(State.searchParam?.terms || []),
+          {
+            terms: [
+              {
+                column: 'productId',
+                value: props?.productId,
+              },
+            ],
+            type: 'and',
+          },
+        ],
+        paging: false,
+        sorts: [{ name: 'createTime', order: 'desc' }],
+      })
+      .then((resp) => {
+        if (resp.status === 200) {
+          State.dataList = resp.result;
+        }
+      });
+  };
+
+  useEffect(() => {
+    State.searchParam = { terms: [] };
+    State.data = props?.value || [];
+    CheckAllData();
+  }, [props?.value]);
+
+  return (
+    <>
+      <Input
+        disabled
+        value={props.value?.map((item) => item.name).join(',')}
+        id={props?.id}
+        addonAfter={
+          <EditOutlined
+            onClick={() => {
+              if (props.disabled) {
+                State.visible = false;
+              } else {
+                State.visible = true;
+              }
+            }}
+          />
+        }
+      />
+      {State.visible && (
+        <Modal
+          maskClosable={false}
+          visible
+          title="选择设备"
+          width="80vw"
+          onCancel={() => {
+            State.visible = false;
+          }}
+          destroyOnClose={true}
+          onOk={() => {
+            State.visible = false;
+            if (props.onChange) {
+              props.onChange(State.data);
+            }
+          }}
+        >
+          <SearchComponent<DeviceInstance>
+            field={columns}
+            enableSave={false}
+            model="simple"
+            onSearch={(data1: any) => {
+              actionRef1.current?.reset?.();
+              State.searchParam = data1;
+              State.data = [];
+              State.dataList = [];
+              CheckAllData();
+            }}
+            target="choose-devices"
+          />
+          <ProTable<DeviceInstance>
+            tableAlertRender={false}
+            rowSelection={{
+              type: 'checkbox',
+              ...rowSelection,
+            }}
+            headerTitle={[
+              <Checkbox
+                indeterminate={State.dataList.length > State.data.length && State.data.length > 0}
+                style={{ marginLeft: 8 }}
+                disabled={!State.dataList.length}
+                checked={State.dataList.length === State.data.length && State.dataList.length > 0}
+                onChange={async (e) => {
+                  if (e.target.checked) {
+                    State.data = State.dataList;
+                  } else {
+                    State.data = [];
+                  }
+                }}
+              >
+                全选
+              </Checkbox>,
+            ]}
+            search={false}
+            columnEmptyText={''}
+            rowKey="id"
+            params={State.searchParam}
+            columns={columns}
+            actionRef={actionRef1}
+            request={async (params) => {
+              return service.queryDetailList({
+                context: {
+                  includeTags: false,
+                  includeBind: false,
+                  includeRelations: false,
+                },
+                ...params,
+                terms: [
+                  ...(params?.terms || []),
+                  {
+                    terms: [
+                      {
+                        column: 'productId',
+                        value: props?.productId,
+                      },
+                    ],
+                    type: 'and',
+                  },
+                ],
+                sorts: [{ name: 'createTime', order: 'desc' }],
+              });
+            }}
+          />
+        </Modal>
+      )}
+    </>
+  );
+});
+
+export default SelectDevices;

+ 2 - 2
src/pages/device/Firmware/Task/Save/index.tsx

@@ -1,10 +1,10 @@
 import { Col, Form, Input, InputNumber, message, Modal, Radio, Row, Select } from 'antd';
 import type { FirmwareItem } from '@/pages/device/Firmware/typings';
-import FSelectDevices from '@/components/FSelectDevices';
 import { useEffect, useRef, useState } from 'react';
 import type { DeviceInstance } from '@/pages/device/Instance/typings';
 import { service } from '@/pages/device/Firmware';
 import { onlyMessage } from '@/utils/util';
+import SelectDevices from '@/pages/device/Firmware/Task/Save/SelectDevices';
 
 interface Props {
   ids: { id: string; productId: string };
@@ -249,7 +249,7 @@ const Save = (props: Props) => {
                       },
                     ]}
                   >
-                    <FSelectDevices productId={ids?.productId || ''} disabled={!!data?.id} />
+                    <SelectDevices productId={ids?.productId || ''} disabled={!!data?.id} />
                   </Form.Item>
                 </Col>
               )}

+ 62 - 39
src/pages/device/Firmware/Task/index.tsx

@@ -1,7 +1,7 @@
 import { PageContainer } from '@ant-design/pro-layout';
 import type { ActionType, ProColumns } from '@jetlinks/pro-table';
 import ProTable from '@jetlinks/pro-table';
-import { message, Tooltip } from 'antd';
+import { message } from 'antd';
 import { useRef, useState } from 'react';
 import { useIntl } from '@@/plugin-locale/localeExports';
 import {
@@ -24,44 +24,6 @@ import SearchComponent from '@/components/SearchComponent';
 import { getMenuPathByParams, MENUS_CODE } from '@/utils/menu';
 import { service } from '@/pages/device/Firmware';
 
-const UpgradeBtn = (props: { data: any; actions: any }) => {
-  const { data, actions } = props;
-  if (data.waiting > 0 && data?.state?.value === 'processing') {
-    return (
-      <a>
-        <Tooltip title={'停止'}>
-          <StopOutlined
-            onClick={async () => {
-              const resp = await service.stopTask(data.id);
-              if (resp.status === 200) {
-                message.success('操作成功!');
-                actions?.reload();
-              }
-            }}
-          />
-        </Tooltip>
-      </a>
-    );
-  } else if (data?.state?.value === 'canceled') {
-    return (
-      <a>
-        <Tooltip title={'继续升级'}>
-          <ControlOutlined
-            onClick={async () => {
-              const resp = await service.startTask(data.id, ['canceled']);
-              if (resp.status === 200) {
-                message.success('操作成功!');
-                actions?.reload();
-              }
-            }}
-          />
-        </Tooltip>
-      </a>
-    );
-  }
-  return null;
-};
-
 export const state = model<{
   current?: FirmwareItem;
   visible: boolean;
@@ -79,6 +41,67 @@ const Task = observer(() => {
   const id = (location as any).query?.id || localStorage.getItem('TaskId');
   const productId = (location as any).query?.productId || localStorage.getItem('TaskProductId');
 
+  const UpgradeBtn = (props: { data: any; actions: any }) => {
+    const { data, actions } = props;
+    if (data.waiting > 0 && data?.state?.value === 'processing') {
+      return (
+        <PermissionButton
+          key={'stop'}
+          type={'link'}
+          style={{ padding: 0 }}
+          isPermission={permission.update}
+          tooltip={{
+            title: '停止',
+          }}
+          onClick={async () => {
+            const resp = await service.stopTask(data.id);
+            if (resp.status === 200) {
+              message.success('操作成功!');
+              actions?.reload();
+            }
+          }}
+        >
+          <StopOutlined />
+        </PermissionButton>
+      );
+    } else if (data?.state?.value === 'canceled') {
+      return (
+        // <a>
+        //   <Tooltip title={'继续升级'}>
+        //     <ControlOutlined
+        //       onClick={async () => {
+        //         const resp = await service.startTask(data.id, ['canceled']);
+        //         if (resp.status === 200) {
+        //           message.success('操作成功!');
+        //           actions?.reload();
+        //         }
+        //       }}
+        //     />
+        //   </Tooltip>
+        // </a>
+        <PermissionButton
+          key={'stop'}
+          type={'link'}
+          style={{ padding: 0 }}
+          isPermission={permission.update}
+          tooltip={{
+            title: '继续升级',
+          }}
+          onClick={async () => {
+            const resp = await service.startTask(data.id, ['canceled']);
+            if (resp.status === 200) {
+              message.success('操作成功!');
+              actions?.reload();
+            }
+          }}
+        >
+          <ControlOutlined />
+        </PermissionButton>
+      );
+    }
+    return null;
+  };
+
   const columns: ProColumns<any>[] = [
     {
       title: '任务名称',

+ 21 - 21
src/pages/device/Instance/Detail/Running/Property/PropertyCard.tsx

@@ -74,27 +74,27 @@ const Property = (props: Props) => {
             ['int', 'long', 'float', 'double', 'string', 'boolean', 'date'].includes(
               data.valueType?.type || '',
             ) && (
-              <Tooltip placement="top" title="指标">
-                <ClockCircleOutlined
-                  onClick={() => {
-                    setIndicatorVisible(true);
-                  }}
-                />
-              </Tooltip>
-              // <PermissionButton
-              //   key={'metrics'}
-              //   onClick={() => {
-              //     setIndicatorVisible(true);
-              //   }}
-              //   tooltip={{
-              //     placement: "top",
-              //     title: devicePermission.update ? "指标" : '暂无权限,请联系管理员'
-              //   }}
-              //   style={{ padding: 0, border: "none", backgroundColor: 'inherit' }}
-              //   isPermission={devicePermission.update}
-              // >
-              //   <ClockCircleOutlined  />
-              // </PermissionButton>
+              // <Tooltip placement="top" title="指标">
+              //   <ClockCircleOutlined
+              //     onClick={() => {
+              //       setIndicatorVisible(true);
+              //     }}
+              //   />
+              // </Tooltip>
+              <PermissionButton
+                key={'metrics'}
+                onClick={() => {
+                  setIndicatorVisible(true);
+                }}
+                tooltip={{
+                  placement: 'top',
+                  title: devicePermission.update ? '指标' : '暂无权限,请联系管理员',
+                }}
+                style={{ padding: 0, border: 'none', backgroundColor: 'inherit' }}
+                isPermission={devicePermission.update}
+              >
+                <ClockCircleOutlined />
+              </PermissionButton>
             )}
           {data.expands?.type?.includes('read') && (
             <Tooltip placement="top" title="获取最新属性值">

+ 26 - 26
src/pages/device/Instance/Detail/Running/Property/index.tsx

@@ -117,32 +117,32 @@ const Property = (props: Props) => {
             ['int', 'long', 'float', 'double', 'string', 'boolean', 'date'].includes(
               record.valueType?.type || '',
             ) && (
-              <Tooltip placement="top" title="指标">
-                <a
-                  onClick={() => {
-                    setIndicatorVisible(true);
-                    setCurrentInfo(record);
-                  }}
-                >
-                  <ClockCircleOutlined />
-                </a>
-              </Tooltip>
-              // <PermissionButton
-              //   type={'link'}
-              //   onClick={() => {
-              //     setVisible(true);
-              //     setCurrentInfo(record);
-              //   }}
-              //   tooltip={{
-              //     placement: "top",
-              //     title: devicePermission.update ? "指标" : '暂无权限,请联系管理员'
-              //   }}
-              //   style={{ padding: 0 }}
-              //   key={'edit'}
-              //   isPermission={devicePermission.update}
-              // >
-              //   <ClockCircleOutlined />
-              // </PermissionButton>
+              // <Tooltip placement="top" title="指标">
+              //   <a
+              //     onClick={() => {
+              //       setIndicatorVisible(true);
+              //       setCurrentInfo(record);
+              //     }}
+              //   >
+              //     <ClockCircleOutlined />
+              //   </a>
+              // </Tooltip>
+              <PermissionButton
+                type={'link'}
+                onClick={() => {
+                  setVisible(true);
+                  setCurrentInfo(record);
+                }}
+                tooltip={{
+                  placement: 'top',
+                  title: devicePermission.update ? '指标' : '暂无权限,请联系管理员',
+                }}
+                style={{ padding: 0 }}
+                key={'edit'}
+                isPermission={devicePermission.update}
+              >
+                <ClockCircleOutlined />
+              </PermissionButton>
             )}
           {record.expands?.type?.includes('read') && (
             <Tooltip placement="top" title="获取最新属性值">

+ 5 - 0
src/pages/device/Instance/service.ts

@@ -375,6 +375,11 @@ class Service extends BaseService<DeviceInstance> {
       method: 'POST',
       data,
     });
+  public queryDetailListNoPaging = (data: any) =>
+    request(`/${SystemConst.API_BASE}/device-instance/detail/_query/no-paging`, {
+      method: 'POST',
+      data,
+    });
   public saveMetadata = (id: string, data: any) =>
     request(`/${SystemConst.API_BASE}/device/instance/${id}/metadata`, {
       method: 'PUT',

+ 2 - 3
src/pages/device/Product/index.tsx

@@ -254,7 +254,7 @@ const Product = observer(() => {
     {
       title: '名称',
       dataIndex: 'name',
-      width: 200,
+      width: 220,
       ellipsis: true,
     },
     {
@@ -291,7 +291,7 @@ const Product = observer(() => {
     {
       title: '接入方式',
       dataIndex: 'accessName',
-      width: 150,
+      width: 220,
       ellipsis: true,
       valueType: 'select',
       // render: (_, row) => {
@@ -363,7 +363,6 @@ const Product = observer(() => {
         defaultMessage: '说明',
       }),
       ellipsis: true,
-      width: 300,
       // hideInSearch: true,
     },
     {

+ 3 - 0
src/pages/device/components/Metadata/Base/Edit/index.tsx

@@ -1173,6 +1173,9 @@ const Edit = observer((props: Props) => {
         }),
         'x-decorator': 'FormItem',
         'x-component': 'JsonParam',
+        'x-component-props': {
+          isFunction: true,
+        },
         'x-reactions': (field) => {
           field.setComponentProps({ keys: 'inputs' });
         },

+ 1 - 1
src/pages/device/components/Metadata/Base/index.tsx

@@ -99,7 +99,7 @@ const BaseMetadata = observer((props: Props) => {
           <EditOutlined />
         </PermissionButton>,
         <PermissionButton
-          isPermission={props.permission.update}
+          isPermission={props.permission.delete}
           type="link"
           key={'delete'}
           style={{ padding: 0 }}

+ 2 - 2
src/pages/device/components/Metadata/index.tsx

@@ -87,10 +87,10 @@ const Metadata = observer((props: Props) => {
                 defaultMessage: '快速导入',
               })}
             </PermissionButton>
-            <PermissionButton isPermission={permission.update} onClick={() => setCat(true)}>
+            <PermissionButton isPermission={true} onClick={() => setCat(true)}>
               {intl.formatMessage({
                 id: 'pages.device.productDetail.metadata',
-                defaultMessage: '物模型',
+                defaultMessage: '物模型TSL',
               })}
               TSL
             </PermissionButton>

+ 1 - 1
src/pages/home/components/CardStatics.tsx

@@ -18,7 +18,7 @@ interface StatisticsProps {
   title: string;
 }
 
-const defaultImage = require('/public/images/home/top-1.png');
+const defaultImage = require('/public/images/home/top-1.svg');
 
 const CardStatistics = (props: StatisticsProps) => {
   return (

+ 1 - 1
src/pages/home/components/Statistics.tsx

@@ -17,7 +17,7 @@ interface StatisticsProps {
   title: string;
 }
 
-const defaultImage = require('/public/images/home/top-1.png');
+const defaultImage = require('/public/images/home/top-1.svg');
 
 const Statistics = (props: StatisticsProps) => {
   return (

+ 4 - 3
src/pages/home/comprehensive/index.tsx

@@ -150,13 +150,13 @@ const Comprehensive = () => {
                 {
                   name: '产品数量',
                   value: productCount,
-                  children: require('/public/images/home/top-2.png'),
+                  children: require('/public/images/home/top-2.svg'),
                   permission: productMessage,
                 },
                 {
                   name: '设备数量',
                   value: deviceCount,
-                  children: require('/public/images/home/top-1.png'),
+                  children: require('/public/images/home/top-1.svg'),
                   permission: deviceMessage,
                 },
               ]}
@@ -188,7 +188,8 @@ const Comprehensive = () => {
             <Body
               title={'平台架构图'}
               english={'PLATFORM ARCHITECTURE DIAGRAM'}
-              url={require('/public/images/home/content1.png')}
+              // url={require('/public/images/home/content1.png')}
+              url={require('/public/images/home/content1.svg')}
             />
           </Col>
         </Row>

+ 1 - 1
src/pages/home/device/index.tsx

@@ -102,7 +102,7 @@ const Device = () => {
             {
               name: '产品数量',
               value: productCount,
-              children: require('/public/images/home/top-2.png'),
+              children: require('/public/images/home/top-2.svg'),
               permission: productMessage,
             },
             {

+ 4 - 2
src/pages/iot-card/Platform/Detail/index.tsx

@@ -15,6 +15,7 @@ const Detail = observer(() => {
   const params = useParams<{ id: string }>();
   const { initialState } = useModel('@@initialState');
   const [docType, setDocType] = useState('');
+  const [loading, setLoading] = useState(false);
 
   const form = useMemo(
     () =>
@@ -364,12 +365,13 @@ const Detail = observer(() => {
 
   const handleSave = async () => {
     const data: any = await form.submit();
+    setLoading(true);
     const res: any = params.id === ':id' ? await service.save(data) : await service.update(data);
     if (res.status === 200) {
       onlyMessage('保存成功');
       history.back();
     }
-    // console.log(data);
+    setLoading(false);
   };
 
   useEffect(() => {
@@ -397,7 +399,7 @@ const Detail = observer(() => {
               />
               <FormButtonGroup.Sticky>
                 <FormButtonGroup.FormItem>
-                  <Button type="primary" onClick={() => handleSave()}>
+                  <Button type="primary" onClick={() => handleSave()} loading={loading}>
                     保存
                   </Button>
                 </FormButtonGroup.FormItem>

+ 28 - 1
src/pages/link/AccessConfig/index.tsx

@@ -85,13 +85,40 @@ const AccessConfig = () => {
       });
   };
 
+  const getUrlParams = (url) => {
+    if (!url.includes('?')) return;
+    const urlStr = url.split('?')[1];
+    const obj = {};
+    const paramsArr = urlStr.split('&');
+    for (let i = 0; i < paramsArr.length; i++) {
+      const arr = paramsArr[i].split('=');
+      obj[arr[0]] = arr[1];
+    }
+    return obj;
+  };
+
   useEffect(() => {
     service.getProviders().then((resp: any) => {
       if (resp.status === 200) {
         Store.set('access-providers', resp.result);
       }
     });
-    handleSearch(param);
+    const paramSearch = param;
+    const paramsQ = getUrlParams(decodeURIComponent(window.location.href));
+    if (paramsQ?.q) {
+      const params = JSON.parse(paramsQ?.q);
+      const terms = [
+        {
+          terms: params.terms1.filter((item) => !!item.value),
+        },
+        {
+          terms: params.terms2.filter((item) => !!item.value),
+          type: params.type,
+        },
+      ];
+      paramSearch.terms = terms;
+    }
+    handleSearch(paramSearch);
   }, []);
 
   return (

+ 4 - 4
src/pages/media/DashBoard/index.tsx

@@ -226,7 +226,7 @@ export default () => {
             ]}
             span={6}
           >
-            <img src={require('/public/images/media/dashboard-1.png')} />
+            <img src={require('/public/images/media/dashboard-1.svg')} />
           </DashBoardTopCard.Item>
           <DashBoardTopCard.Item
             title={'通道数量'}
@@ -245,7 +245,7 @@ export default () => {
             ]}
             span={6}
           >
-            <img src={require('/public/images/media/dashboard-2.png')} />
+            <img src={require('/public/images/media/dashboard-2.svg')} />
           </DashBoardTopCard.Item>
           <DashBoardTopCard.Item
             title={'录像数量'}
@@ -258,7 +258,7 @@ export default () => {
             ]}
             span={6}
           >
-            <img src={require('/public/images/media/dashboard-3.png')} />
+            <img src={require('/public/images/media/dashboard-3.svg')} />
           </DashBoardTopCard.Item>
           <DashBoardTopCard.Item
             title={
@@ -278,7 +278,7 @@ export default () => {
             ]}
             span={6}
           >
-            <img src={require('/public/images/media/dashboard-4.png')} />
+            <img src={require('/public/images/media/dashboard-4.svg')} />
           </DashBoardTopCard.Item>
         </DashBoardTopCard>
         <DashBoard

+ 1 - 1
src/pages/media/Device/Channel/service.ts

@@ -28,7 +28,7 @@ class Service extends BaseService<ChannelItem> {
 
   // 云台控制-停止
   ptzStop = (deviceId: string, channelId: string) =>
-    request(`${this.uri}/device/${deviceId}/${channelId}/_stop`, { method: 'POST' });
+    request(`${this.uri}/device/${deviceId}/${channelId}/_ptz/STOP`, { method: 'POST' });
 
   // 云台控制-缩放、转向等
   ptzTool = (deviceId: string, channelId: string, direct: string, speed: number = 90) =>

+ 3 - 1
src/pages/media/Device/Save/SaveProduct.tsx

@@ -29,6 +29,8 @@ export default (props: SaveProps) => {
         terms: [{ column: 'provider', value: props.type }],
         pageSize: 100,
       });
+    } else {
+      setExtendFormItem([]);
     }
   }, [visible]);
 
@@ -57,7 +59,7 @@ export default (props: SaveProps) => {
         setLoading(false);
         if (deployResp.status === 200) {
           if (reload) {
-            reload(resp.result.id, resp.result.name);
+            reload(resp.result.id, resp.result);
           }
           onClose();
         } else {

+ 16 - 4
src/pages/media/Device/Save/index.tsx

@@ -24,6 +24,8 @@ const Save = () => {
   const [accessType, setAccessType] = useState(DefaultAccessType);
   const [productList, setProductList] = useState<any[]>([]);
   const [oldPassword, setOldPassword] = useState('');
+  const [loading, setLoading] = useState(false);
+
   const img1 = require('/public/images/media/doc1.png');
   const img2 = require('/public/images/media/doc2.png');
   const img3 = require('/public/images/media/doc3.png');
@@ -81,9 +83,11 @@ const Save = () => {
       if (formData.id === '') {
         delete extraFormData.id;
       }
+      setLoading(true);
       const resp = id
         ? await service.updateData(channel, id, { ...extraFormData, channel })
         : await service.saveData(channel, { ...extraFormData, channel });
+      setLoading(false);
       if (resp.status === 200) {
         form.resetFields();
         onlyMessage('操作成功');
@@ -265,7 +269,9 @@ const Save = () => {
                           onSelect={(_: any, node: any) => {
                             const pwd = node.configuration ? node.configuration.access_pwd : '';
                             form.setFieldsValue({
-                              password: pwd,
+                              others: {
+                                access_pwd: pwd,
+                              },
                             });
                           }}
                         />
@@ -379,7 +385,7 @@ const Save = () => {
                 </Form.Item>
                 <Col span={24}>
                   <Form.Item>
-                    <Button type="primary" htmlType="submit">
+                    <Button type="primary" htmlType="submit" loading={loading}>
                       保存
                     </Button>
                   </Form.Item>
@@ -462,11 +468,17 @@ const Save = () => {
           close={() => {
             setProductVisible(false);
           }}
-          reload={(productId: string, name: string) => {
+          reload={(productId: string, data: any) => {
             form.setFieldsValue({ productId });
             productList.push({
               id: productId,
-              name,
+              name: data.name,
+            });
+            const pwd = data.configuration ? data.configuration.access_pwd : '';
+            form.setFieldsValue({
+              others: {
+                access_pwd: pwd,
+              },
             });
             setProductList([...productList]);
           }}

+ 2 - 2
src/pages/media/Home/index.tsx

@@ -109,12 +109,12 @@ export default () => {
               {
                 name: '设备数量',
                 value: deviceTotal || 0,
-                children: require('/public/images/home/top-1.png'),
+                children: require('/public/images/home/top-1.svg'),
               },
               {
                 name: '通道数量',
                 value: channelTotal || 0,
-                children: require('/public/images/home/top-2.png'),
+                children: require('/public/images/home/top-2.svg'),
               },
             ]}
             extra={

+ 1 - 1
src/pages/media/SplitScreen/service.ts

@@ -14,7 +14,7 @@ export const ptzStart = (deviceId: string, channelId: string, type: string) =>
 
 // 云台控制-停止
 export const ptzStop = (deviceId: string, channelId: string) =>
-  request(`${url}/device/${deviceId}/${channelId}/_stop`, { method: 'POST' });
+  request(`${url}/device/${deviceId}/${channelId}/_ptz/STOP`, { method: 'POST' });
 
 // 云台控制-缩放、转向等
 export const ptzTool = (deviceId: string, channelId: string, direct: string, speed: number = 90) =>

+ 4 - 5
src/pages/notice/Config/Detail/doc/AliyunVoice.tsx

@@ -19,14 +19,13 @@ const AliyunVoice = () => {
       <h1>2.通知配置说明</h1>
       <div>
         <h2>1、RegionID</h2>
-        <div>
-          阿里云内部给每台机器设置的唯一编号。请根据购买的阿里云服务器阿里云地域和可用区对照表地址:https://help.aliyun.com/document_detail/40654.html?spm=a2c6h.13066369.0.0.54a174710O7rWH
-        </div>
+        <div>阿里云服务地域与对应的RegionID。请根据购买的阿里云服务器地域进行选择。</div>
       </div>
       <h2>2、AccesskeyID/Secret</h2>
       <div>
-        <div>用于程序通知方式调用云服务费API的用户标识和秘钥公众号开发者身份的密码</div>
-        <div>获取路径:“阿里云管理控制台”--“用户头像”--“”--“AccessKey管理”--“查看”</div>
+        <div>
+          用于程序通知方式调用云服务费API的用户标识和秘钥获取路径:“阿里云管理控制台”--“用户头像”--“”--“AccessKey管理”--“查看”
+        </div>
       </div>
       <div className={'image'}>
         <Image width="100%" src={accessKey} />

+ 16 - 20
src/pages/notice/Config/Detail/index.tsx

@@ -2,7 +2,7 @@ import { PageContainer } from '@ant-design/pro-layout';
 import { createForm, onFieldValueChange, onFormInit } from '@formily/core';
 import { Card, Col, Input, Row } from 'antd';
 import { ISchema } from '@formily/json-schema';
-import { useMemo, useState } from 'react';
+import { useEffect, useMemo, useState } from 'react';
 import { createSchemaField, observer } from '@formily/react';
 import {
   ArrayTable,
@@ -35,8 +35,9 @@ import { PermissionButton } from '@/components';
 import usePermissions from '@/hooks/permission';
 import FAutoComplete from '@/components/FAutoComplete';
 import Webhook from './doc/Webhook';
-// import { useModel } from '@@/plugin-model/useModel';
+import { useModel } from '@@/plugin-model/useModel';
 import { typeArray } from '@/components/ProTableCard/CardItems/noticeTemplate';
+import RegionIdList from './regionId';
 
 export const docMap = {
   weixin: {
@@ -63,7 +64,7 @@ export const docMap = {
 
 const Detail = observer(() => {
   const { id } = useParams<{ id: string }>();
-  // const { initialState } = useModel('@@initialState');
+  const { initialState } = useModel('@@initialState');
   const [typeItem, setTypeItem] = useState<string>('email');
   const [providerItem, setProviderItem] = useState<string>('embedded');
   const [loading, setLoading] = useState<boolean>(false);
@@ -112,15 +113,15 @@ const Detail = observer(() => {
     [],
   );
 
-  // useEffect(() => {
-  //   setTimeout(() => {
-  //     if (initialState?.settings?.title) {
-  //       document.title = `通知配置 - ${initialState?.settings?.title}`;
-  //     } else {
-  //       document.title = '通知配置';
-  //     }
-  //   }, 0);
-  // }, []);
+  useEffect(() => {
+    setTimeout(() => {
+      if (initialState?.settings?.title) {
+        document.title = `通知配置 - ${initialState?.settings?.title}`;
+      } else {
+        document.title = '通知配置';
+      }
+    }, 0);
+  }, []);
 
   const SchemaField = createSchemaField({
     components: {
@@ -402,16 +403,11 @@ const Detail = observer(() => {
                 title: 'RegionId',
                 required: true,
                 'x-component-props': {
-                  placeholder: '请输入regionId',
+                  placeholder: '请选择regionId',
                 },
-                'x-component': 'Input',
+                'x-component': 'Select',
                 'x-decorator': 'FormItem',
-                'x-validator': [
-                  {
-                    max: 64,
-                    message: '最多可输入64个字符',
-                  },
-                ],
+                enum: RegionIdList,
               },
               accessKeyId: {
                 title: 'AccessKeyId',

+ 119 - 0
src/pages/notice/Config/Detail/regionId.ts

@@ -0,0 +1,119 @@
+//  数据来源 https://help.aliyun.com/document_detail/188196.html
+export default [
+  /** 公共云 */
+  //中国地区(包含中国香港、中国澳门,不包含中国台湾)
+  {
+    value: 'cn-qingdao',
+    label: '华北1(青岛)',
+  },
+  {
+    value: 'cn-beijing',
+    label: '华北2(北京)',
+  },
+  {
+    value: 'cn-zhangjiakou',
+    label: '华北3(张家口)',
+  },
+  {
+    value: 'cn-huhehaote',
+    label: '华北5(呼和浩特)',
+  },
+  {
+    value: 'cn-wulanchabu',
+    label: '华北6(乌兰察布)',
+  },
+  {
+    value: 'cn-hangzhou',
+    label: '华东1(杭州)',
+  },
+  {
+    value: 'cn-shanghai',
+    label: '华东2(上海)',
+  },
+  {
+    value: 'cn-nanjing',
+    label: '华东5 (南京-本地地域)',
+  },
+  {
+    value: 'cn-fuzhou',
+    label: '华东6(福州-本地地域)',
+  },
+  {
+    value: 'cn-shenzhen',
+    label: '华南1(深圳)',
+  },
+  {
+    value: 'cn-heyuan',
+    label: '华南2(河源)',
+  },
+  {
+    value: 'cn-guangzhou',
+    label: '华南3(广州)',
+  },
+  {
+    value: 'cn-chengdu',
+    label: '西南1(成都)',
+  },
+  {
+    value: 'cn-hongkong',
+    label: '中国香港',
+  },
+
+  //其他国家和地区
+  {
+    value: 'ap-southeast-1',
+    label: '新加坡',
+  },
+  {
+    value: 'ap-southeast-2',
+    label: '澳大利亚(悉尼)',
+  },
+  {
+    value: 'ap-southeast-3',
+    label: '马来西亚(吉隆坡)',
+  },
+  {
+    value: 'ap-southeast-5',
+    label: '印度尼西亚(雅加达)',
+  },
+  {
+    value: 'ap-southeast-6',
+    label: '菲律宾(马尼拉)',
+  },
+  {
+    value: 'ap-southeast-7',
+    label: '泰国(曼谷)',
+  },
+  {
+    value: 'ap-south-1',
+    label: '印度(孟买)',
+  },
+  {
+    value: 'ap-northeast-1',
+    label: '日本(东京)',
+  },
+  {
+    value: 'ap-northeast-2',
+    label: '韩国(首尔)',
+  },
+  {
+    value: 'us-west-1',
+    label: '美国(硅谷)',
+  },
+  {
+    value: 'us-east-1',
+    label: '美国(弗吉尼亚)',
+  },
+  {
+    value: 'eu-central-1',
+    label: '德国(法兰克福)',
+  },
+  {
+    value: 'eu-west-1',
+    label: '英国(伦敦)',
+  },
+  {
+    value: 'me-east-1',
+    label: '阿联酋(迪拜)',
+  },
+];

+ 5 - 18
src/pages/notice/Config/index.tsx

@@ -22,7 +22,6 @@ import SearchComponent from '@/components/SearchComponent';
 import { getMenuPathByParams, MENUS_CODE } from '@/utils/menu';
 import { history } from 'umi';
 import { model } from '@formily/reactive';
-import moment from 'moment';
 import { PermissionButton, ProTableCard } from '@/components';
 import NoticeConfig from '@/components/ProTableCard/CardItems/noticeConfig';
 import Debug from '@/pages/notice/Config/Debug';
@@ -49,7 +48,7 @@ const Config = observer(() => {
   const actionRef = useRef<ActionType>();
   // const location = useLocation<{ id: string }>();
 
-  const { permission: configPermission } = usePermissions('notice');
+  const { permission: configPermission } = usePermissions('notice/Config');
   // const id = (location as any).query?.id;
 
   const columns: ProColumns<ConfigItem>[] = [
@@ -129,17 +128,12 @@ const Config = observer(() => {
           type="link"
           style={{ padding: 0 }}
           isPermission={configPermission.export}
-          onClick={() =>
-            downloadObject(
-              record,
-              `通知配置${record.name}-${moment(new Date()).format('YYYY/MM/DD HH:mm:ss')}`,
-            )
-          }
+          onClick={() => downloadObject(record, `通知配置_${record.name}`)}
           key="download"
           tooltip={{
             title: intl.formatMessage({
-              id: 'pages.data.option.download',
-              defaultMessage: '下载配置',
+              id: 'pages.data.option.export',
+              defaultMessage: '导出',
             }),
           }}
         >
@@ -376,14 +370,7 @@ const Config = observer(() => {
                         type={'link'}
                         key="export"
                         isPermission={configPermission.export}
-                        onClick={() =>
-                          downloadObject(
-                            record,
-                            `通知配置${record.name}-${moment(new Date()).format(
-                              'YYYY/MM/DD HH:mm:ss',
-                            )}`,
-                          )
-                        }
+                        onClick={() => downloadObject(record, `通知配置_${record.name}`)}
                       >
                         <ArrowDownOutlined />
                         导出

+ 17 - 17
src/pages/notice/Template/Detail/index.tsx

@@ -27,12 +27,11 @@ import {
 import { createSchemaField, observer } from '@formily/react';
 import type { ISchema } from '@formily/json-schema';
 import styles from './index.less';
-import { useMemo, useRef, useState } from 'react';
+import { useEffect, useMemo, useRef, useState } from 'react';
 import FUpload from '@/components/Upload';
 import { useParams } from 'umi';
 import { PageContainer } from '@ant-design/pro-layout';
 import { Card, Col, Row, Tooltip } from 'antd';
-import { typeList } from '@/pages/notice';
 import { configService, service } from '@/pages/notice/Template';
 import FBraftEditor from '@/components/FBraftEditor';
 import { onlyMessage, phoneRegEx, useAsyncDataSource } from '@/utils/util';
@@ -49,9 +48,10 @@ import { PermissionButton } from '@/components';
 import usePermissions from '@/hooks/permission';
 import FMonacoEditor from '@/components/FMonacoEditor';
 import Webhook from './doc/Webhook';
-// import { useModel } from '@@/plugin-model/useModel';
+import { useModel } from '@@/plugin-model/useModel';
 import { QuestionCircleOutlined } from '@ant-design/icons';
 import { typeArray } from '@/components/ProTableCard/CardItems/noticeTemplate';
+import { typeList } from '../..';
 
 export const docMap = {
   weixin: {
@@ -81,7 +81,7 @@ const Detail = observer(() => {
   const [typeItem, setTypeItem] = useState<string>('email');
   const [providerItem, setProviderItem] = useState<string>('embedded');
   const [loading, setLoading] = useState<boolean>(false);
-  // const { initialState } = useModel('@@initialState');
+  const { initialState } = useModel('@@initialState');
   // 正则提取${}里面的值
   const pattern = /(?<=\$\{).*?(?=\})/g;
 
@@ -474,18 +474,18 @@ const Detail = observer(() => {
     [id],
   );
 
-  // useEffect(() => {
-  //   setTimeout(() => {
-  //     if (initialState?.settings?.title) {
-  //       document.title = `通知模板 - ${initialState?.settings?.title}`;
-  //     } else {
-  //       document.title = '通知模板';
-  //     }
-  //   }, 0);
-  //   // if (state.current) {
-  //   //   form.setValues(state.current);
-  //   // }
-  // }, []);
+  useEffect(() => {
+    setTimeout(() => {
+      if (initialState?.settings?.title) {
+        document.title = `通知模板 - ${initialState?.settings?.title}`;
+      } else {
+        document.title = '通知模板';
+      }
+    }, 0);
+    // if (state.current) {
+    //   form.setValues(state.current);
+    // }
+  }, []);
 
   const SchemaField = createSchemaField({
     components: {
@@ -635,7 +635,7 @@ const Detail = observer(() => {
           dependencies: ['type'],
           fulfill: {
             state: {
-              visible: '{{!!$deps[0] && $deps[0] !== "email" && $deps[0] !== "webhook"}}',
+              hidden: '{{!(!!$deps[0] && $deps[0] !== "email" && $deps[0] !== "webhook")}}',
             },
           },
         },

+ 3 - 7
src/pages/notice/Template/index.tsx

@@ -21,7 +21,6 @@ import { model } from '@formily/reactive';
 import Debug from './Debug';
 import Log from '@/pages/notice/Template/Log';
 import { downloadObject, onlyMessage } from '@/utils/util';
-import moment from 'moment';
 import { PermissionButton, ProTableCard } from '@/components';
 import NoticeCard, {
   typeList,
@@ -49,7 +48,7 @@ const Template = observer(() => {
   // const id = (location as any).query?.id;
   const actionRef = useRef<ActionType>();
 
-  const { permission: templatePermission } = usePermissions('notice');
+  const { permission: templatePermission } = usePermissions('notice/Template');
 
   const columns: ProColumns<TemplateItem>[] = [
     {
@@ -113,7 +112,7 @@ const Template = observer(() => {
           tooltip={{ title: '导出' }}
           isPermission={templatePermission.export}
           onClick={() => {
-            downloadObject(record, `${record.name}-${moment(new Date()).format('YYYY_MM_DD')}`);
+            downloadObject(record, `通知模板_${record.name}`);
           }}
         >
           <ArrowDownOutlined />
@@ -308,10 +307,7 @@ const Template = observer(() => {
                 key="export"
                 isPermission={templatePermission.export}
                 onClick={() => {
-                  downloadObject(
-                    record,
-                    `${record.name}-${moment(new Date()).format('YYYY/MM/DD HH:mm:ss')}`,
-                  );
+                  downloadObject(record, `通知模板_${record.name}`);
                 }}
               >
                 <ArrowDownOutlined />

+ 1 - 1
src/pages/rule-engine/Alarm/Configuration/Save/Scene/index.tsx

@@ -137,7 +137,7 @@ export default () => {
             key="button"
             icon={<PlusOutlined />}
             type="primary"
-            isPermission={permission.update}
+            isPermission={permission.add}
             onClick={() => {
               setVisible(true);
             }}

+ 1 - 0
src/pages/rule-engine/Scene/Save/action/ListItem/Item.tsx

@@ -547,6 +547,7 @@ export default (props: ItemProps) => {
       )}
       {triggerVisible && (
         <TriggerAlarm
+          id={FormModel.current?.id || ''}
           close={() => {
             setTriggerVisible(false);
           }}

+ 3 - 3
src/pages/rule-engine/Scene/Save/action/TriggerAlarm/index.tsx

@@ -5,10 +5,10 @@ import { Store } from 'jetlinks-store';
 import { useIntl } from '@@/plugin-locale/localeExports';
 import { queryDefaultLevel, queryAlarmList, queryAlarmCount } from '../service';
 import encodeQuery from '@/utils/encodeQuery';
-import { FormModel } from '@/pages/rule-engine/Scene/Save';
 
 interface Props {
   close: () => void;
+  id: string;
 }
 
 export default (props: Props) => {
@@ -20,7 +20,7 @@ export default (props: Props) => {
     queryAlarmCount(
       encodeQuery({
         terms: {
-          'id$rule-bind-alarm': FormModel.current.id,
+          'id$rule-bind-alarm': props.id, // FormModel.current.id,
         },
       }),
     ).then((resp) => {
@@ -162,7 +162,7 @@ export default (props: Props) => {
                 terms: [
                   {
                     column: 'id',
-                    value: FormModel.current.id,
+                    value: props.id,
                     termType: 'rule-bind-alarm',
                   },
                 ],

+ 3 - 1
src/pages/rule-engine/Scene/Save/action/notify/VariableDefinitions.tsx

@@ -38,7 +38,9 @@ export default forwardRef((props: Props, ref) => {
       const rules: any[] = [];
       rules.push({
         validator: async (_: any, value: any) => {
-          if ((type === 'file' || type === 'link') && !value) {
+          if (type === 'file') {
+            return Promise.resolve();
+          } else if (type === 'link' && !value) {
             return Promise.reject(new Error('请输入' + item.name));
           } else if (type === 'tag' && !value) {
             return Promise.reject(new Error('请选择' + item.name));

+ 3 - 7
src/pages/rule-engine/Scene/Save/components/DatePickerFormat/index.tsx

@@ -22,13 +22,9 @@ export default (props: DatePickerFormat) => {
     v: DatePickerProps['value'],
     f: DatePickerProps['format'],
   ): moment.Moment => {
-    if (f === 'string') {
-      const _format = handleFormat(f);
-      return moment(moment(v, defaultFormat), _format).utc();
-    } else {
-      const _format = handleFormat(f);
-      return moment(moment(v, defaultFormat), _format);
-    }
+    console.log(v);
+    const _format = handleFormat(f);
+    return moment(v, _format);
   };
 
   return (

+ 12 - 5
src/pages/rule-engine/Scene/Save/index.tsx

@@ -1,14 +1,14 @@
 import { PageContainer } from '@ant-design/pro-layout';
-import { Button, Card, Form, FormInstance, Input } from 'antd';
+import { Card, Form, FormInstance, Input } from 'antd';
 import useLocation from '@/hooks/route/useLocation';
 import Device from '../Save/device/index';
 import Manual from '../Save/manual/index';
 import Timer from '../Save/timer/index';
-import { Ellipsis, TitleComponent } from '@/components';
+import { Ellipsis, PermissionButton, TitleComponent } from '@/components';
 import { observable } from '@formily/reactive';
 import { observer } from '@formily/react';
 import type { FormModelType } from '@/pages/rule-engine/Scene/typings';
-import { useEffect, useCallback, useState } from 'react';
+import React, { useEffect, useCallback, useState } from 'react';
 import { service } from '@/pages/rule-engine/Scene';
 import './index.less';
 import { onlyMessage, randomString } from '@/utils/util';
@@ -75,6 +75,7 @@ export default observer(() => {
   const history = useHistory();
   const [form] = Form.useForm();
   const [saveLoading, setSaveLoading] = useState(false);
+  const { permission, getOtherPermission } = PermissionButton.usePermission('rule-engine/Scene');
 
   const FormModelInit = () => {
     FormModel.current = {
@@ -230,9 +231,15 @@ export default observer(() => {
             <Input.TextArea showCount maxLength={200} placeholder={'请输入说明'} rows={4} />
           </Form.Item>
           <Form.Item>
-            <Button type="primary" htmlType="submit" onClick={submit} loading={saveLoading}>
+            <PermissionButton
+              key={'update'}
+              type={'primary'}
+              isPermission={getOtherPermission([permission.update, permission.add])}
+              onClick={submit}
+              loading={saveLoading}
+            >
               保存
-            </Button>
+            </PermissionButton>
           </Form.Item>
         </Form>
       </Card>

+ 1 - 1
src/pages/system/DataSource/Save/index.tsx

@@ -128,7 +128,7 @@ const Save = (props: Props) => {
                       resolve('');
                     } else {
                       const arr = value.split(':');
-                      if ((arr?.[0] === 'jdbc' || arr?.[0] === 'r2dbc') && arr?.[1] === 'mysql') {
+                      if (arr?.[0] === 'jdbc' || arr?.[0] === 'r2dbc') {
                         resolve('');
                       } else {
                         resolve('请输入正确的URL');

+ 4 - 0
src/pages/system/Menu/Detail/buttons.tsx

@@ -290,6 +290,7 @@ export default (props: ButtonsProps) => {
             resetForm();
             setVisible(false);
           }}
+          bodyStyle={{ paddingBottom: 0 }}
           confirmLoading={loading}
         >
           <Form form={form} layout={'vertical'}>
@@ -340,6 +341,9 @@ export default (props: ButtonsProps) => {
                 defaultMessage: '权限',
               })}
               required={true}
+              style={{
+                marginBottom: 0,
+              }}
             >
               <Input
                 allowClear

+ 7 - 77
src/pages/system/Menu/Setting/baseMenu.ts

@@ -76,10 +76,6 @@ export default [
                     actions: ['query'],
                   },
                   {
-                    permission: 'template',
-                    actions: ['query'],
-                  },
-                  {
                     permission: 'user-third-party-manager',
                     actions: ['query', 'save'],
                   },
@@ -97,10 +93,6 @@ export default [
                     permission: 'notifier',
                     actions: ['query'],
                   },
-                  {
-                    permission: 'template',
-                    actions: ['query'],
-                  },
                 ],
               },
               {
@@ -143,10 +135,6 @@ export default [
                     permission: 'notifier',
                     actions: ['query'],
                   },
-                  {
-                    permission: 'template',
-                    actions: ['query'],
-                  },
                 ],
               },
               {
@@ -157,10 +145,6 @@ export default [
                     permission: 'notifier',
                     actions: ['query', 'save'],
                   },
-                  {
-                    permission: 'template',
-                    actions: ['query', 'save'],
-                  },
                 ],
               },
               {
@@ -171,10 +155,6 @@ export default [
                     permission: 'notifier',
                     actions: ['query', 'delete'],
                   },
-                  {
-                    permission: 'template',
-                    actions: ['query', 'delete'],
-                  },
                 ],
               },
               {
@@ -185,10 +165,6 @@ export default [
                     permission: 'notifier',
                     actions: ['query', 'save'],
                   },
-                  {
-                    permission: 'template',
-                    actions: ['query', 'save'],
-                  },
                 ],
               },
               {
@@ -199,10 +175,6 @@ export default [
                     permission: 'notifier',
                     actions: ['query', 'save'],
                   },
-                  {
-                    permission: 'template',
-                    actions: ['query', 'save'],
-                  },
                 ],
               },
             ],
@@ -219,37 +191,11 @@ export default [
             showPage: ['template'],
             permissions: [],
             buttons: [
-              // {
-              //   id: 'bind',
-              //   name: '同步用户',
-              //   permissions: [
-              //     {
-              //       permission: 'notifier',
-              //       actions: ['query'],
-              //     },
-              //     {
-              //       permission: 'template',
-              //       actions: ['query'],
-              //     },
-              //     {
-              //       permission: 'user-third-party-manager',
-              //       actions: ['query', 'save'],
-              //     },
-              //     {
-              //       permission: 'user',
-              //       actions: ['query'],
-              //     },
-              //   ],
-              // },
               {
                 id: 'view',
                 name: '查看',
                 permissions: [
                   {
-                    permission: 'notifier',
-                    actions: ['query'],
-                  },
-                  {
                     permission: 'template',
                     actions: ['query'],
                   },
@@ -260,10 +206,6 @@ export default [
                 name: '通知记录',
                 permissions: [
                   {
-                    permission: 'notifier',
-                    actions: ['query'],
-                  },
-                  {
                     permission: 'template',
                     actions: ['query'],
                   },
@@ -292,10 +234,6 @@ export default [
                 name: '导出',
                 permissions: [
                   {
-                    permission: 'notifier',
-                    actions: ['query'],
-                  },
-                  {
                     permission: 'template',
                     actions: ['query'],
                   },
@@ -306,10 +244,6 @@ export default [
                 name: '导入',
                 permissions: [
                   {
-                    permission: 'notifier',
-                    actions: ['query', 'save'],
-                  },
-                  {
                     permission: 'template',
                     actions: ['query', 'save'],
                   },
@@ -320,10 +254,6 @@ export default [
                 name: '删除',
                 permissions: [
                   {
-                    permission: 'notifier',
-                    actions: ['query', 'delete'],
-                  },
-                  {
                     permission: 'template',
                     actions: ['query', 'delete'],
                   },
@@ -335,7 +265,7 @@ export default [
                 permissions: [
                   {
                     permission: 'notifier',
-                    actions: ['query', 'save'],
+                    actions: ['query'],
                   },
                   {
                     permission: 'template',
@@ -349,7 +279,7 @@ export default [
                 permissions: [
                   {
                     permission: 'notifier',
-                    actions: ['query', 'save'],
+                    actions: ['query'],
                   },
                   {
                     permission: 'template',
@@ -2750,11 +2680,11 @@ export default [
           { permission: 'media-channel', actions: ['query', 'save', 'delete'] },
         ],
         buttons: [
-          {
-            id: 'view',
-            name: '查看',
-            permissions: [{ permission: 'media-device', actions: ['query'] }],
-          },
+          // {
+          //   id: 'view',
+          //   name: '查看',
+          //   permissions: [{ permission: 'media-device', actions: ['query'] }],
+          // },
         ],
       },
       {

+ 1 - 1
src/pages/system/Menu/components/permission.less

@@ -11,7 +11,7 @@
   }
 
   .permission-content {
-    max-height: 400px;
+    max-height: 350px;
     overflow-y: auto;
 
     .permission-items {

+ 1 - 1
src/pages/system/User/Save/index.tsx

@@ -490,7 +490,7 @@ const Save = (props: Props) => {
       onOk={save}
       width="35vw"
       permissionCode={'system/User'}
-      permission={['update']}
+      permission={['update', 'add']}
     >
       <Form form={form} layout="vertical">
         <SchemaField schema={schema} scope={{ useAsyncDataSource, getRole, getOrg }} />

+ 1 - 1
src/utils/util.ts

@@ -53,7 +53,7 @@ export const downloadFileByUrl = (url: string, name: string, type: string) => {
 export const downloadObject = (record: Record<string, any>, fileName: string, format?: string) => {
   // 创建隐藏的可下载链接
   const ghostLink = document.createElement('a');
-  ghostLink.download = `${record?.name || ''}${fileName}_${moment(new Date()).format(
+  ghostLink.download = `${fileName ? '' : record?.name}${fileName}_${moment(new Date()).format(
     format || 'YYYY_MM_DD',
   )}.json`;
   ghostLink.style.display = 'none';