cacode commited on
Commit
cfce07c
·
verified ·
1 Parent(s): 4fb3744

Upload 67 files

Browse files
app/static/style.css CHANGED
@@ -857,6 +857,175 @@ textarea {
857
  gap: 14px;
858
  }
859
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
860
  .task-editor-card {
861
  gap: 16px;
862
  }
@@ -1069,7 +1238,8 @@ textarea {
1069
  .task-page-grid,
1070
  .users-admin-grid,
1071
  .presence-admin-grid,
1072
- .review-live-grid {
 
1073
  grid-template-columns: 1fr;
1074
  }
1075
 
@@ -1083,12 +1253,23 @@ textarea {
1083
  .task-carousel-head,
1084
  .carousel-controls,
1085
  .presence-item,
1086
- .activity-actions {
 
 
1087
  grid-template-columns: 1fr;
1088
  flex-direction: column;
1089
  align-items: stretch;
1090
  }
1091
 
 
 
 
 
 
 
 
 
 
1092
  .task-flip-book {
1093
  min-height: 900px;
1094
  }
@@ -1135,3 +1316,6 @@ textarea {
1135
  .compact-stack-item {
1136
  padding: 10px 12px;
1137
  }
 
 
 
 
857
  gap: 14px;
858
  }
859
 
860
+ .activity-catalog-panel {
861
+ overflow: hidden;
862
+ }
863
+
864
+ .activity-catalog-head {
865
+ margin-bottom: 20px;
866
+ }
867
+
868
+ .published-activity-list {
869
+ display: grid;
870
+ gap: 20px;
871
+ }
872
+
873
+ .published-activity-card {
874
+ position: relative;
875
+ display: grid;
876
+ grid-template-columns: minmax(0, 1.55fr) minmax(290px, 0.9fr);
877
+ gap: 22px;
878
+ padding: 22px;
879
+ border-radius: 30px;
880
+ background:
881
+ radial-gradient(circle at 100% 0%, rgba(241, 193, 107, 0.18), transparent 28%),
882
+ linear-gradient(135deg, rgba(255, 255, 255, 0.92), rgba(236, 248, 239, 0.9));
883
+ border: 1px solid rgba(78, 148, 97, 0.16);
884
+ box-shadow: 0 20px 38px rgba(86, 127, 93, 0.12);
885
+ }
886
+
887
+ .published-activity-card::before {
888
+ content: "";
889
+ position: absolute;
890
+ inset: 0 auto auto 24px;
891
+ width: 110px;
892
+ height: 5px;
893
+ border-radius: 999px;
894
+ background: linear-gradient(90deg, rgba(96, 175, 114, 0.9), rgba(241, 193, 107, 0.82));
895
+ }
896
+
897
+ .published-activity-main,
898
+ .published-activity-side,
899
+ .published-activity-form {
900
+ display: grid;
901
+ gap: 16px;
902
+ }
903
+
904
+ .published-activity-main {
905
+ min-width: 0;
906
+ align-content: start;
907
+ }
908
+
909
+ .published-activity-head {
910
+ display: flex;
911
+ align-items: flex-start;
912
+ justify-content: space-between;
913
+ gap: 16px;
914
+ }
915
+
916
+ .published-activity-title {
917
+ margin: 4px 0 0;
918
+ font-size: 1.8rem;
919
+ line-height: 1.12;
920
+ }
921
+
922
+ .published-activity-badges {
923
+ display: flex;
924
+ flex-wrap: wrap;
925
+ justify-content: flex-end;
926
+ gap: 10px;
927
+ }
928
+
929
+ .published-activity-metrics,
930
+ .published-activity-notes {
931
+ display: grid;
932
+ gap: 14px;
933
+ }
934
+
935
+ .published-activity-metrics {
936
+ grid-template-columns: repeat(3, minmax(0, 1fr));
937
+ }
938
+
939
+ .published-activity-notes {
940
+ grid-template-columns: repeat(2, minmax(0, 1fr));
941
+ }
942
+
943
+ .activity-metric-card,
944
+ .activity-note-card {
945
+ padding: 16px 18px;
946
+ border-radius: 22px;
947
+ border: 1px solid rgba(78, 148, 97, 0.12);
948
+ }
949
+
950
+ .activity-metric-card {
951
+ background: rgba(255, 255, 255, 0.78);
952
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.68);
953
+ }
954
+
955
+ .activity-note-card {
956
+ background: rgba(244, 250, 245, 0.88);
957
+ }
958
+
959
+ .activity-metric-card span,
960
+ .activity-note-card span {
961
+ display: block;
962
+ font-size: 0.8rem;
963
+ letter-spacing: 0.08em;
964
+ text-transform: uppercase;
965
+ color: var(--muted);
966
+ }
967
+
968
+ .activity-metric-card strong,
969
+ .activity-note-card strong {
970
+ display: block;
971
+ margin-top: 8px;
972
+ line-height: 1.45;
973
+ color: var(--primary-deep);
974
+ }
975
+
976
+ .activity-metric-card strong {
977
+ font-size: 1.02rem;
978
+ }
979
+
980
+ .published-activity-side {
981
+ align-content: start;
982
+ padding: 18px;
983
+ border-radius: 26px;
984
+ background: linear-gradient(180deg, rgba(247, 252, 248, 0.94), rgba(229, 244, 233, 0.88));
985
+ border: 1px solid rgba(78, 148, 97, 0.14);
986
+ }
987
+
988
+ .published-activity-side .btn,
989
+ .published-delete-form .btn {
990
+ width: 100%;
991
+ justify-content: center;
992
+ }
993
+
994
+ .published-toggle-row {
995
+ display: flex;
996
+ align-items: center;
997
+ justify-content: space-between;
998
+ gap: 14px;
999
+ padding: 14px 16px;
1000
+ border-radius: 20px;
1001
+ background: rgba(255, 255, 255, 0.78);
1002
+ border: 1px solid rgba(78, 148, 97, 0.12);
1003
+ }
1004
+
1005
+ .published-toggle-row > div {
1006
+ display: grid;
1007
+ gap: 4px;
1008
+ }
1009
+
1010
+ .published-toggle-row strong {
1011
+ font-size: 1rem;
1012
+ color: var(--primary-deep);
1013
+ }
1014
+
1015
+ .published-toggle-row span {
1016
+ font-size: 0.88rem;
1017
+ line-height: 1.45;
1018
+ color: var(--muted);
1019
+ }
1020
+
1021
+ .published-toggle-row input {
1022
+ width: 20px;
1023
+ height: 20px;
1024
+ padding: 0;
1025
+ margin: 0;
1026
+ flex: 0 0 auto;
1027
+ }
1028
+
1029
  .task-editor-card {
1030
  gap: 16px;
1031
  }
 
1238
  .task-page-grid,
1239
  .users-admin-grid,
1240
  .presence-admin-grid,
1241
+ .review-live-grid,
1242
+ .published-activity-card {
1243
  grid-template-columns: 1fr;
1244
  }
1245
 
 
1253
  .task-carousel-head,
1254
  .carousel-controls,
1255
  .presence-item,
1256
+ .activity-actions,
1257
+ .published-activity-head,
1258
+ .published-toggle-row {
1259
  grid-template-columns: 1fr;
1260
  flex-direction: column;
1261
  align-items: stretch;
1262
  }
1263
 
1264
+ .published-activity-metrics,
1265
+ .published-activity-notes {
1266
+ grid-template-columns: 1fr;
1267
+ }
1268
+
1269
+ .published-activity-badges {
1270
+ justify-content: flex-start;
1271
+ }
1272
+
1273
  .task-flip-book {
1274
  min-height: 900px;
1275
  }
 
1316
  .compact-stack-item {
1317
  padding: 10px 12px;
1318
  }
1319
+
1320
+
1321
+
app/templates/admin_activities.html CHANGED
@@ -80,46 +80,91 @@
80
  </form>
81
  </article>
82
 
83
- <article class="glass-card table-panel">
84
- <div class="section-head">
85
  <div>
86
  <p class="eyebrow">Published Activities</p>
87
  <h3>已发布活动</h3>
 
88
  </div>
89
  </div>
90
- <div class="stack-list">
91
  {% for activity in activities %}
92
- <article class="stack-item stack-item-block">
93
- <div>
94
- <strong>{{ activity.title }}</strong>
95
- <p class="muted">{{ activity.start_at|datetime_local }} 至 {{ activity.deadline_at|datetime_local }}</p>
96
- <p class="muted">{{ activity.tasks|length }} 个任务 · 创建人 {{ activity.created_by.display_name }}</p>
97
- <p class="muted">线索间隔:{{ activity.clue_interval_minutes if activity.clue_interval_minutes is not none else '与活动开始同步' }}</p>
98
- <div class="chip-row">
99
- <span class="chip">{{ '用户端可见' if activity.is_visible else '用户端隐藏' }}</span>
100
- <span class="chip">{{ '排行榜可见' if activity.leaderboard_visible else '排行榜隐藏' }}</span>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
101
  </div>
102
  </div>
103
- <div class="activity-actions">
104
- <a class="btn btn-primary small-btn" href="/admin/activities/{{ activity.id }}/edit">编辑活动</a>
105
- <form method="post" action="/admin/activities/{{ activity.id }}/visibility" class="inline-form visibility-form">
106
- <label class="checkbox-row compact-checkbox">
 
 
 
 
 
 
107
  <input type="checkbox" name="is_visible" {% if activity.is_visible %}checked{% endif %} />
108
- <span>用户可见活动</span>
109
  </label>
110
- <label class="checkbox-row compact-checkbox">
 
 
 
 
111
  <input type="checkbox" name="leaderboard_visible" {% if activity.leaderboard_visible %}checked{% endif %} />
112
- <span>用户可见排行榜</span>
113
  </label>
114
- <button class="btn btn-secondary small-btn" type="submit">保存</button>
115
  </form>
116
- <form method="post" action="/admin/activities/{{ activity.id }}/delete" class="inline-form">
117
- <button class="btn btn-danger small-btn" type="submit" onclick="return confirm('确定删除这个活动吗?相关任务、审核记录和本地提交图片都会一并删除。');">删除活动</button>
 
118
  </form>
119
- </div>
120
  </article>
121
  {% else %}
122
- <p class="muted">还没有活动,先发布一个吧。</p>
 
 
 
123
  {% endfor %}
124
  </div>
125
  </article>
 
80
  </form>
81
  </article>
82
 
83
+ <article class="glass-card table-panel activity-catalog-panel">
84
+ <div class="section-head activity-catalog-head">
85
  <div>
86
  <p class="eyebrow">Published Activities</p>
87
  <h3>已发布活动</h3>
88
+ <p class="mini-note">把活动信息、可见性开关和危险操作拆分展示,管理起来会更清晰。</p>
89
  </div>
90
  </div>
91
+ <div class="published-activity-list">
92
  {% for activity in activities %}
93
+ <article class="published-activity-card">
94
+ <div class="published-activity-main">
95
+ <div class="published-activity-head">
96
+ <div>
97
+ <p class="eyebrow">Activity {{ loop.index }}</p>
98
+ <h3 class="published-activity-title">{{ activity.title }}</h3>
99
+ </div>
100
+ <div class="published-activity-badges">
101
+ <span class="status-badge {% if activity.is_visible %}status-approved{% else %}status-rejected{% endif %}">
102
+ {{ '活动可见' if activity.is_visible else '活动隐藏' }}
103
+ </span>
104
+ <span class="status-badge {% if activity.leaderboard_visible %}status-approved{% else %}status-rejected{% endif %}">
105
+ {{ '排行可见' if activity.leaderboard_visible else '排行隐藏' }}
106
+ </span>
107
+ </div>
108
+ </div>
109
+
110
+ <div class="published-activity-metrics">
111
+ <div class="activity-metric-card">
112
+ <span>开始时间</span>
113
+ <strong>{{ activity.start_at|datetime_local }}</strong>
114
+ </div>
115
+ <div class="activity-metric-card">
116
+ <span>截止时间</span>
117
+ <strong>{{ activity.deadline_at|datetime_local }}</strong>
118
+ </div>
119
+ <div class="activity-metric-card">
120
+ <span>任务数量</span>
121
+ <strong>{{ activity.tasks|length }} 个任务</strong>
122
+ </div>
123
+ </div>
124
+
125
+ <div class="published-activity-notes">
126
+ <div class="activity-note-card">
127
+ <span>创建人</span>
128
+ <strong>{{ activity.created_by.display_name }}</strong>
129
+ </div>
130
+ <div class="activity-note-card">
131
+ <span>线索间隔</span>
132
+ <strong>{{ activity.clue_interval_minutes if activity.clue_interval_minutes is not none else '与活动开始同步' }}</strong>
133
+ </div>
134
  </div>
135
  </div>
136
+
137
+ <aside class="published-activity-side">
138
+ <a class="btn btn-primary" href="/admin/activities/{{ activity.id }}/edit">编辑活动</a>
139
+
140
+ <form method="post" action="/admin/activities/{{ activity.id }}/visibility" class="published-activity-form">
141
+ <label class="published-toggle-row">
142
+ <div>
143
+ <strong>活动对用户可见</strong>
144
+ <span>关闭后,用户端不会显示,也不能直接进入此活动。</span>
145
+ </div>
146
  <input type="checkbox" name="is_visible" {% if activity.is_visible %}checked{% endif %} />
 
147
  </label>
148
+ <label class="published-toggle-row">
149
+ <div>
150
+ <strong>排行榜对用户可见</strong>
151
+ <span>管理员始终可见,这里只控制普通用户是否能看到排行榜。</span>
152
+ </div>
153
  <input type="checkbox" name="leaderboard_visible" {% if activity.leaderboard_visible %}checked{% endif %} />
 
154
  </label>
155
+ <button class="btn btn-secondary" type="submit">保存显示设置</button>
156
  </form>
157
+
158
+ <form method="post" action="/admin/activities/{{ activity.id }}/delete" class="published-delete-form">
159
+ <button class="btn btn-danger" type="submit" onclick="return confirm('确定删除这个活动吗?相关任务、审核记录和本地提交图片都会一并删除。');">删除活动</button>
160
  </form>
161
+ </aside>
162
  </article>
163
  {% else %}
164
+ <article class="empty-state">
165
+ <h3>还没有活动</h3>
166
+ <p>先在左侧发布一个活动,这里会自动整理成更清晰的管理卡片。</p>
167
+ </article>
168
  {% endfor %}
169
  </div>
170
  </article>