global-context-bar.component.html 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. <section class="global-context-bar" aria-label="工作台上下文">
  2. <div class="context-fields">
  3. <label class="context-field scope-field">
  4. <span>工作空间</span>
  5. <select
  6. aria-label="选择工作空间"
  7. [disabled]="disabled"
  8. [value]="context.workspaceId"
  9. (change)="onSelection('workspaceId', $event)"
  10. >
  11. <option value="">请选择</option>
  12. @if (isMissingOption(workspaceOptions, context.workspaceId)) {
  13. <option [value]="context.workspaceId">{{ context.workspaceId }}</option>
  14. }
  15. @for (option of workspaceOptions; track option.value) {
  16. <option [value]="option.value" [disabled]="option.disabled">{{ option.label }}</option>
  17. }
  18. </select>
  19. </label>
  20. <label class="context-field compact-field">
  21. <span>平台</span>
  22. <select
  23. aria-label="选择平台"
  24. [disabled]="disabled"
  25. [value]="context.platform"
  26. (change)="onSelection('platform', $event)"
  27. >
  28. <option value="">请选择</option>
  29. @if (isMissingOption(platformOptions, context.platform)) {
  30. <option [value]="context.platform">{{ context.platform }}</option>
  31. }
  32. @for (option of platformOptions; track option.value) {
  33. <option [value]="option.value" [disabled]="option.disabled">{{ option.label }}</option>
  34. }
  35. </select>
  36. </label>
  37. <span class="context-divider" aria-hidden="true"></span>
  38. <label class="context-field">
  39. <span>店铺</span>
  40. <select
  41. aria-label="选择店铺"
  42. [disabled]="disabled"
  43. [value]="context.shopId"
  44. (change)="onSelection('shopId', $event)"
  45. >
  46. <option value="">全部店铺</option>
  47. @if (isMissingOption(shopOptions, context.shopId)) {
  48. <option [value]="context.shopId">{{ context.shopId }}</option>
  49. }
  50. @for (option of shopOptions; track option.value) {
  51. <option [value]="option.value" [disabled]="option.disabled">{{ option.label }}</option>
  52. }
  53. </select>
  54. </label>
  55. <label class="context-field">
  56. <span>类目</span>
  57. <select
  58. aria-label="选择类目"
  59. [disabled]="disabled"
  60. [value]="context.categoryId"
  61. (change)="onSelection('categoryId', $event)"
  62. >
  63. <option value="">全部类目</option>
  64. @if (isMissingOption(categoryOptions, context.categoryId)) {
  65. <option [value]="context.categoryId">{{ context.categoryId }}</option>
  66. }
  67. @for (option of categoryOptions; track option.value) {
  68. <option [value]="option.value" [disabled]="option.disabled">{{ option.label }}</option>
  69. }
  70. </select>
  71. </label>
  72. <label class="context-field product-field">
  73. <span>商品</span>
  74. <select
  75. aria-label="选择商品"
  76. [disabled]="disabled"
  77. [value]="context.productId"
  78. (change)="onSelection('productId', $event)"
  79. >
  80. <option value="">全部商品</option>
  81. @if (isMissingOption(productOptions, context.productId)) {
  82. <option [value]="context.productId">{{ context.productId }}</option>
  83. }
  84. @for (option of productOptions; track option.value) {
  85. <option [value]="option.value" [disabled]="option.disabled">{{ option.label }}</option>
  86. }
  87. </select>
  88. </label>
  89. <div class="context-field date-field">
  90. <span>日期</span>
  91. @for (renderKey of dateRangeRenderKeys; track renderKey) {
  92. <app-date-range-picker
  93. [initialRange]="initialDateRange"
  94. (rangeConfirm)="onDateRangeConfirm($event)"
  95. />
  96. }
  97. </div>
  98. <label class="context-field comparison-field">
  99. <span>对比</span>
  100. <select
  101. aria-label="选择对比周期"
  102. [disabled]="disabled"
  103. [value]="context.comparisonPeriod"
  104. (change)="onComparisonChange($event)"
  105. >
  106. @for (option of comparisonOptions; track option.value) {
  107. <option [value]="option.value">{{ option.label }}</option>
  108. }
  109. </select>
  110. </label>
  111. </div>
  112. <div class="context-meta">
  113. <div
  114. class="availability"
  115. [attr.data-status]="effectiveStatus || 'unknown'"
  116. [title]="effectiveStatusDetail || statusLabel"
  117. >
  118. @if (effectiveStatus === 'ready') {
  119. <lucide-icon [img]="icons.check" [size]="15" aria-hidden="true" />
  120. } @else if (effectiveStatus === 'stale') {
  121. <lucide-icon [img]="icons.clock" [size]="15" aria-hidden="true" />
  122. } @else {
  123. <lucide-icon [img]="icons.alert" [size]="15" aria-hidden="true" />
  124. }
  125. <span>{{ statusLabel }}</span>
  126. </div>
  127. <span class="last-updated">
  128. @if (effectiveLastUpdated) {
  129. 更新于 {{ effectiveLastUpdated | date:'yyyy-MM-dd HH:mm' }}
  130. } @else {
  131. 更新时间未上报
  132. }
  133. </span>
  134. <div class="context-actions">
  135. <button
  136. type="button"
  137. class="icon-command"
  138. title="清空筛选"
  139. aria-label="清空筛选"
  140. [disabled]="disabled || !hasActiveFilters"
  141. (click)="clearFilters()"
  142. >
  143. <lucide-icon [img]="icons.reset" [size]="16" aria-hidden="true" />
  144. </button>
  145. <button
  146. type="button"
  147. class="refresh-command"
  148. [class.is-loading]="refreshing"
  149. [disabled]="disabled || refreshing"
  150. (click)="requestRefresh()"
  151. >
  152. <lucide-icon [img]="icons.refresh" [size]="16" aria-hidden="true" />
  153. <span>{{ refreshing ? '刷新中' : '刷新' }}</span>
  154. </button>
  155. </div>
  156. </div>
  157. </section>