chore(release): freeze v0.2.0
版本冻结 v0.2.0,固化 2026-09-24 本轮全部变更。 admin-web: - 修复旧物善用管理页缺失样式类 .workspace-view / .view-header / .table-wrap, 此前页面无内边距导致内容被侧边栏遮挡、窄屏表格无横向滚动 - 修复服务统计页缺失样式类 .dashboard-grid / .dashboard-card / .stat-row, 此前 8 个指标卡退化为裸文本堆叠 - 补齐未定义的 --shadow-card 变量(财务编辑面板阴影此前失效) - 侧边栏 13 项导航由手写重复改为 NAV_ITEMS 数据驱动,并按业务顺序重排 - AdminIcon 补齐 coins / phone / volunteer / flag / calendar / recycle 语义图标 - 侧边栏行高与间距压缩使 13 项一屏放下,滚动条隐藏 - 小于等于 760px 断点导航由 display:none 改为横向滚动,移动端恢复可切换 api: - prisma.config.ts 显式加载仓库根 .env,修复 prisma generate / migrate 取不到 DATABASE_URL - dev / bootstrap:admin / test:integration 增加 tsx --env-file-if-exists=../../.env miniprogram: - custom-tab-bar 选中态与申请表单分步流程抽为可测纯函数并补充单测 - 页面完整性门禁脚本增强 工程: - 版本统一升位 0.1.0 到 0.2.0(根与 4 个 workspace 包) - .gitignore 增加 .pnpm-store/、.workbuddy/、微信开发者工具私人配置 与仓库根目录误生成的工程配置,避免本地产物与机器相关信息入库 验证:pnpm lint 通过、pnpm test:unit 19 个用例通过、miniprogram typecheck 通过、 admin-web typecheck 与 build 通过、pnpm install --frozen-lockfile 未改写 lockfile、 无头浏览器端到端登录复验通过、待提交内容密钥扫描无命中。 说明:本轮定位并排除了一起 Prisma 生成目录残缺事故——API 开发进程与并发的 prisma generate 争抢同一输出目录,Windows 文件锁导致只生成 34/56 个模型文件, 使 TS 全量类型解析失败并产生数千条 lint 报错;停止竞争进程后干净重新生成即恢复。 该生成目录已被 .gitignore 忽略,不进入版本库。
This commit is contained in:
+27
-104
@@ -26,7 +26,9 @@ const errors = reactive<{ username?: string; password?: string }>({});
|
||||
const submitting = ref(false);
|
||||
const showPassword = ref(false);
|
||||
const message = ref('');
|
||||
const activeView = ref<
|
||||
const activeView = ref<ViewKey>('dashboard');
|
||||
|
||||
type ViewKey =
|
||||
| 'dashboard'
|
||||
| 'applications'
|
||||
| 'beneficiaries'
|
||||
@@ -39,8 +41,23 @@ const activeView = ref<
|
||||
| 'notifications'
|
||||
| 'statistics'
|
||||
| 'financial-disclosures'
|
||||
| 'old-items'
|
||||
>('dashboard');
|
||||
| 'old-items';
|
||||
|
||||
const NAV_ITEMS: ReadonlyArray<{ key: ViewKey; label: string; icon: string }> = [
|
||||
{ key: 'dashboard', label: '工作概览', icon: 'dashboard' },
|
||||
{ key: 'applications', label: '服务申请', icon: 'application' },
|
||||
{ key: 'cases', label: '服务工单', icon: 'case' },
|
||||
{ key: 'follow-ups', label: '回访工作台', icon: 'phone' },
|
||||
{ key: 'beneficiaries', label: '服务对象', icon: 'people' },
|
||||
{ key: 'volunteers', label: '志愿者审核', icon: 'volunteer' },
|
||||
{ key: 'projects', label: '公益项目', icon: 'flag' },
|
||||
{ key: 'activities', label: '活动与报名', icon: 'calendar' },
|
||||
{ key: 'content', label: '内容发布', icon: 'content' },
|
||||
{ key: 'financial-disclosures', label: '财务公开', icon: 'coins' },
|
||||
{ key: 'notifications', label: '通知投递', icon: 'notification' },
|
||||
{ key: 'statistics', label: '服务统计', icon: 'chart' },
|
||||
{ key: 'old-items', label: '旧物善用管理', icon: 'recycle' },
|
||||
];
|
||||
|
||||
onMounted(() => auth.restore());
|
||||
|
||||
@@ -144,108 +161,14 @@ async function logout(): Promise<void> {
|
||||
</div>
|
||||
<nav>
|
||||
<button
|
||||
:class="['nav-item', { 'nav-item--active': activeView === 'old-items' }]"
|
||||
v-for="item in NAV_ITEMS"
|
||||
:key="item.key"
|
||||
:class="['nav-item', { 'nav-item--active': activeView === item.key }]"
|
||||
type="button"
|
||||
:aria-current="activeView === 'old-items' ? 'page' : undefined"
|
||||
@click="activeView = 'old-items'"
|
||||
:aria-current="activeView === item.key ? 'page' : undefined"
|
||||
@click="activeView = item.key"
|
||||
>
|
||||
<AdminIcon name="content" />旧物善用管理
|
||||
</button>
|
||||
<button
|
||||
:class="['nav-item', { 'nav-item--active': activeView === 'dashboard' }]"
|
||||
type="button"
|
||||
:aria-current="activeView === 'dashboard' ? 'page' : undefined"
|
||||
@click="activeView = 'dashboard'"
|
||||
>
|
||||
<AdminIcon name="dashboard" />工作概览
|
||||
</button>
|
||||
<button
|
||||
:class="['nav-item', { 'nav-item--active': activeView === 'applications' }]"
|
||||
type="button"
|
||||
:aria-current="activeView === 'applications' ? 'page' : undefined"
|
||||
@click="activeView = 'applications'"
|
||||
>
|
||||
<AdminIcon name="application" />服务申请
|
||||
</button>
|
||||
<button
|
||||
:class="['nav-item', { 'nav-item--active': activeView === 'statistics' }]"
|
||||
type="button"
|
||||
:aria-current="activeView === 'statistics' ? 'page' : undefined"
|
||||
@click="activeView = 'statistics'"
|
||||
>
|
||||
<AdminIcon name="chart" />服务统计
|
||||
</button>
|
||||
<button
|
||||
:class="['nav-item', { 'nav-item--active': activeView === 'content' }]"
|
||||
type="button"
|
||||
:aria-current="activeView === 'content' ? 'page' : undefined"
|
||||
@click="activeView = 'content'"
|
||||
>
|
||||
<AdminIcon name="content" />内容发布
|
||||
</button>
|
||||
<button
|
||||
:class="['nav-item', { 'nav-item--active': activeView === 'financial-disclosures' }]"
|
||||
type="button"
|
||||
:aria-current="activeView === 'financial-disclosures' ? 'page' : undefined"
|
||||
@click="activeView = 'financial-disclosures'"
|
||||
>
|
||||
<AdminIcon name="content" />财务公开
|
||||
</button>
|
||||
<button
|
||||
:class="['nav-item', { 'nav-item--active': activeView === 'notifications' }]"
|
||||
type="button"
|
||||
:aria-current="activeView === 'notifications' ? 'page' : undefined"
|
||||
@click="activeView = 'notifications'"
|
||||
>
|
||||
<AdminIcon name="notification" />通知投递
|
||||
</button>
|
||||
<button
|
||||
:class="['nav-item', { 'nav-item--active': activeView === 'beneficiaries' }]"
|
||||
type="button"
|
||||
:aria-current="activeView === 'beneficiaries' ? 'page' : undefined"
|
||||
@click="activeView = 'beneficiaries'"
|
||||
>
|
||||
<AdminIcon name="people" />服务对象
|
||||
</button>
|
||||
<button
|
||||
:class="['nav-item', { 'nav-item--active': activeView === 'cases' }]"
|
||||
type="button"
|
||||
:aria-current="activeView === 'cases' ? 'page' : undefined"
|
||||
@click="activeView = 'cases'"
|
||||
>
|
||||
<AdminIcon name="case" />服务工单
|
||||
</button>
|
||||
<button
|
||||
:class="['nav-item', { 'nav-item--active': activeView === 'follow-ups' }]"
|
||||
type="button"
|
||||
:aria-current="activeView === 'follow-ups' ? 'page' : undefined"
|
||||
@click="activeView = 'follow-ups'"
|
||||
>
|
||||
回访工作台
|
||||
</button>
|
||||
<button
|
||||
:class="['nav-item', { 'nav-item--active': activeView === 'volunteers' }]"
|
||||
type="button"
|
||||
:aria-current="activeView === 'volunteers' ? 'page' : undefined"
|
||||
@click="activeView = 'volunteers'"
|
||||
>
|
||||
志愿者审核
|
||||
</button>
|
||||
<button
|
||||
:class="['nav-item', { 'nav-item--active': activeView === 'projects' }]"
|
||||
type="button"
|
||||
:aria-current="activeView === 'projects' ? 'page' : undefined"
|
||||
@click="activeView = 'projects'"
|
||||
>
|
||||
公益项目
|
||||
</button>
|
||||
<button
|
||||
:class="['nav-item', { 'nav-item--active': activeView === 'activities' }]"
|
||||
type="button"
|
||||
:aria-current="activeView === 'activities' ? 'page' : undefined"
|
||||
@click="activeView = 'activities'"
|
||||
>
|
||||
活动与报名
|
||||
<AdminIcon :name="item.icon" />{{ item.label }}
|
||||
</button>
|
||||
</nav>
|
||||
<p class="phase-note">仅限授权人员访问,关键业务操作均记录审计。</p>
|
||||
@@ -276,7 +199,7 @@ async function logout(): Promise<void> {
|
||||
<FinancialDisclosuresView v-else-if="activeView === 'financial-disclosures'" />
|
||||
<OldItemsView v-else-if="activeView === 'old-items'" />
|
||||
<NotificationDeliveriesView v-else-if="activeView === 'notifications'" />
|
||||
<StatisticsView v-else />
|
||||
<StatisticsView v-else-if="activeView === 'statistics'" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
Reference in New Issue
Block a user