admin_new P0+P1 全批次合并 (84 commits) #2

Merged
direv merged 85 commits from develop into main 2026-08-07 11:27:17 +08:00
8 changed files with 125 additions and 163 deletions
Showing only changes of commit 50c9e144e9 - Show all commits

View File

@ -1,6 +1,8 @@
<script setup lang="ts"> <script setup lang="ts">
/** /**
* F006 订单详情 - 完整版 (W5.x.x+5 整改) * F006 订单详情 - W10 A6 标准化
*
* W10 A6: 套 PageHeader (返回按钮 slot)
* *
* 沿用老 vue order/order-detail.vue 1379 行完整功能: * 沿用老 vue order/order-detail.vue 1379 行完整功能:
* - 4 个 tab: 订单信息 / 商品明细 / 物流信息 / 付款发票 * - 4 个 tab: 订单信息 / 商品明细 / 物流信息 / 付款发票
@ -19,6 +21,7 @@ import { ref, onMounted, watch, computed, reactive } from 'vue'
import { useRoute, useRouter } from 'vue-router' import { useRoute, useRouter } from 'vue-router'
import { ElMessage, ElMessageBox } from 'element-plus' import { ElMessage, ElMessageBox } from 'element-plus'
import { httpGet } from '@/utils/request' import { httpGet } from '@/utils/request'
import PageHeader from '@/components/PageHeader/PageHeader.vue'
interface OrderDetail { interface OrderDetail {
id: string id: string
@ -325,9 +328,9 @@ watch(orderId, load)
<template> <template>
<div class="rr-order-detail"> <div class="rr-order-detail">
<div class="rr-page-header"> <PageHeader title="订单详情" :sub="detail?.orderCode || ''">
<el-button text @click="onBack">← 返回订单列表</el-button> <el-button text @click="onBack">← 返回订单列表</el-button>
</div> </PageHeader>
<div v-if="loading" class="rr-loading"> <div v-if="loading" class="rr-loading">
<el-skeleton :rows="6" animated /> <el-skeleton :rows="6" animated />
@ -547,7 +550,6 @@ watch(orderId, load)
<style scoped lang="scss"> <style scoped lang="scss">
.rr-order-detail { max-width: 1400px; } .rr-order-detail { max-width: 1400px; }
.rr-page-header { margin-bottom: 16px; }
.rr-card { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-lg); overflow: hidden; margin-bottom: 16px; } .rr-card { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-lg); overflow: hidden; margin-bottom: 16px; }
.rr-card-header { padding: 16px 20px; border-bottom: 1px solid var(--border); display: flex; justify-content: space-between; align-items: center; } .rr-card-header { padding: 16px 20px; border-bottom: 1px solid var(--border); display: flex; justify-content: space-between; align-items: center; }
.rr-card-title { font-size: 15px; font-weight: 600; color: var(--ink); margin: 0; } .rr-card-title { font-size: 15px; font-weight: 600; color: var(--ink); margin: 0; }

View File

@ -1,12 +1,16 @@
<script setup lang="ts"> <script setup lang="ts">
/** /**
* F006 商品单位 - W3.x C P1.1 * F006 商品单位 - W10 A4 标准化
*
* W10 A4: 套 PageHeader/SearchBar 标准化模板 (前端筛选转 SearchBar)
* 走 /other/goodunit/list 真 API (返 data: [...] 数组, 共 112 行) * 走 /other/goodunit/list 真 API (返 data: [...] 数组, 共 112 行)
* 字段: id/name/type/supplierId/enterpriseId/createTime * 字段: id/name/type/supplierId/enterpriseId/createTime
*/ */
import { onMounted, ref, computed } from 'vue' import { onMounted, ref, computed } from 'vue'
import { httpGet } from '@/utils/request' import { httpGet } from '@/utils/request'
import DataTable from '@/components/DataTable/DataTable.vue' import DataTable from '@/components/DataTable/DataTable.vue'
import PageHeader from '@/components/PageHeader/PageHeader.vue'
import SearchBar from '@/components/SearchBar/SearchBar.vue'
interface GoodUnit { interface GoodUnit {
id: string id: string
@ -66,14 +70,17 @@ onMounted(load)
<template> <template>
<div class="rr-page"> <div class="rr-page">
<div class="rr-page-header"> <PageHeader title="商品单位" :sub="`商品计量单位管理 (共 ${list.length} 个, 筛选后 ${filtered.length} 个)`" />
<h2 class="rr-page-title">商品单位</h2>
<p class="rr-page-sub">商品计量单位管理(共 {{ list.length }} 个, 筛选后 {{ filtered.length }} 个)</p>
</div>
<div class="rr-filters"> <SearchBar
<el-input v-model="filterKw" placeholder="按名称筛选" clearable class="rr-filter-input" size="default" /> v-model:filters="{ kw: filterKw }"
</div> :fields="[
{ key: 'kw', label: '名称', type: 'text', placeholder: '按名称筛选' }
]"
:show-reset="false"
@search="() => {}"
@reset="() => { filterKw = '' }"
/>
<div class="rr-card"> <div class="rr-card">
<DataTable <DataTable
@ -112,11 +119,5 @@ onMounted(load)
<style scoped lang="scss"> <style scoped lang="scss">
.rr-page { max-width: 1400px; } .rr-page { max-width: 1400px; }
.rr-page-header { margin-bottom: 16px; }
.rr-page-title { font-size: 22px; font-weight: 600; letter-spacing: -0.02em; color: var(--ink); margin-bottom: 4px; }
.rr-page-sub { color: var(--ink-3); font-size: 13px; }
.rr-filters { margin-bottom: 16px; display: flex; gap: 8px; }
.rr-filter-input { width: 280px; }
.rr-card { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-lg); overflow: hidden; }
.rr-time { font-family: 'SF Mono', Menlo, monospace; font-size: 12px; color: var(--ink-2); } .rr-time { font-family: 'SF Mono', Menlo, monospace; font-size: 12px; color: var(--ink-2); }
</style> </style>

View File

@ -1,11 +1,14 @@
<script setup lang="ts"> <script setup lang="ts">
/** /**
* F006 操作指南 - W3.x C P0.4 * F006 操作指南 - W10 A7 标准化
*
* W10 A7: 套 PageHeader (无搜索, 简洁)
* 走 /other/operateguide/page * 走 /other/operateguide/page
*/ */
import { onMounted, ref, reactive } from 'vue' import { onMounted, ref, reactive } from 'vue'
import { httpGet } from '@/utils/request' import { httpGet } from '@/utils/request'
import DataTable from '@/components/DataTable/DataTable.vue' import DataTable from '@/components/DataTable/DataTable.vue'
import PageHeader from '@/components/PageHeader/PageHeader.vue'
interface Guide { interface Guide {
id: string id: string
@ -43,10 +46,7 @@ onMounted(load)
<template> <template>
<div class="rr-page"> <div class="rr-page">
<div class="rr-page-header"> <PageHeader title="操作指南" :sub="`操作指南内容 (共 ${total} 条)`" />
<h2 class="rr-page-title">内容列表</h2>
<p class="rr-page-sub">操作指南内容(共 {{ total }} 条)</p>
</div>
<div class="rr-card"> <div class="rr-card">
<DataTable :columns="columns" :data="list" :loading="loading" :total="total" :page="query.page" :limit="query.limit" :show-pagination="true" row-key="id" empty-text="暂无内容" @page-change="onPageChange" /> <DataTable :columns="columns" :data="list" :loading="loading" :total="total" :page="query.page" :limit="query.limit" :show-pagination="true" row-key="id" empty-text="暂无内容" @page-change="onPageChange" />
</div> </div>
@ -55,8 +55,5 @@ onMounted(load)
<style scoped lang="scss"> <style scoped lang="scss">
.rr-page { max-width: 1400px; } .rr-page { max-width: 1400px; }
.rr-page-header { margin-bottom: 20px; }
.rr-page-title { font-size: 22px; font-weight: 600; letter-spacing: -0.02em; color: var(--ink); margin-bottom: 4px; }
.rr-page-sub { color: var(--ink-3); font-size: 13px; }
.rr-card { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-lg); overflow: hidden; } .rr-card { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-lg); overflow: hidden; }
</style> </style>

View File

@ -1,6 +1,8 @@
<script setup lang="ts"> <script setup lang="ts">
/** /**
* F006 营销活动管理 * F006 营销活动管理 - W10 A7 标准化
*
* W10 A7: 套 PageHeader/SearchBar 标准化模板
* *
* 后端端点 (ActivityZoneController @ /supplier/activityzone): * 后端端点 (ActivityZoneController @ /supplier/activityzone):
* GET /supplier/activityzone/page 分页列表 * GET /supplier/activityzone/page 分页列表
@ -9,6 +11,8 @@
import { onMounted, ref, reactive } from 'vue' import { onMounted, ref, reactive } from 'vue'
import { httpGet } from '@/utils/request' import { httpGet } from '@/utils/request'
import DataTable from '@/components/DataTable/DataTable.vue' import DataTable from '@/components/DataTable/DataTable.vue'
import PageHeader from '@/components/PageHeader/PageHeader.vue'
import SearchBar from '@/components/SearchBar/SearchBar.vue'
interface Activity { interface Activity {
id: string id: string
@ -98,24 +102,20 @@ onMounted(() => { load() })
<template> <template>
<div class="rr-sys-user"> <div class="rr-sys-user">
<div class="rr-page-header"> <PageHeader title="营销活动" :sub="`共 ${total} 个活动`" />
<div class="rr-page-titles">
<h2 class="rr-page-title">营销活动</h2>
<p class="rr-page-sub">共 {{ total }} 个活动</p>
</div>
<div class="rr-page-actions">
<el-button @click="onReset" class="rr-btn-secondary">重置</el-button>
</div>
</div>
<div class="rr-filters-row"> <SearchBar
<el-input v-model="filters.activityName" placeholder="活动名搜索" clearable class="rr-username-input" size="small" @keyup.enter="onSearch" /> v-model:filters="filters"
<el-select v-model="filters.status" placeholder="状态" class="rr-type-select" clearable size="small"> :fields="[
<el-option value="1" label="开启" /> { key: 'activityName', label: '活动名', type: 'text', placeholder: '活动名搜索' },
<el-option value="0" label="关闭" /> { key: 'status', label: '状态', type: 'select', options: [
</el-select> { value: 1, label: '开启' },
<el-button class="rr-btn-secondary" size="small" @click="onSearch">查询</el-button> { value: 0, label: '关闭' }
</div> ] }
]"
@search="onSearch"
@reset="onReset"
/>
<div class="rr-list-card"> <div class="rr-list-card">
<DataTable <DataTable
@ -184,15 +184,7 @@ onMounted(() => { load() })
<style scoped> <style scoped>
.rr-sys-user { padding: 16px; } .rr-sys-user { padding: 16px; }
.rr-page-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 14px; } .rr-list-card { background: var(--surface); border-radius: 12px; padding: 4px; }
.rr-page-titles { display: flex; flex-direction: column; gap: 2px; } .rr-time { font-family: 'SF Mono', Menlo, Monaco, Consolas, monospace; font-size: 12px; color: var(--ink-2); }
.rr-page-title { margin: 0; font-size: 18px; font-weight: 600; color: var(--el-text-color-primary); } .rr-muted { color: var(--ink-3); font-size: 12px; }
.rr-page-sub { margin: 0; font-size: 12px; color: var(--el-text-color-secondary); }
.rr-page-actions { display: flex; gap: 8px; }
.rr-filters-row { display: flex; align-items: center; gap: 8px; margin-bottom: 14px; padding: 12px 16px; background: var(--el-fill-color-light); border-radius: 8px; }
.rr-username-input { width: 240px; }
.rr-type-select { width: 140px; }
.rr-list-card { background: var(--el-bg-color); border-radius: 12px; padding: 4px; }
.rr-time { font-family: 'SF Mono', Menlo, Monaco, Consolas, monospace; font-size: 12px; color: var(--el-text-color-regular); }
.rr-muted { color: var(--el-text-color-placeholder); font-size: 12px; }
</style> </style>

View File

@ -1,6 +1,8 @@
<script setup lang="ts"> <script setup lang="ts">
/** /**
* F006 优惠券管理 - W7 P0 整改 (沿用老 vue supplier/coupon.vue 116 行) * F006 优惠券管理 - W10 A4 标准化
*
* W10 A4: 套 PageHeader/SearchBar 标准化模板 (沿用老 vue supplier/coupon.vue 116 行)
* *
* 端点 /supplier/coupon/page 200 OK 真数据, 老字段: * 端点 /supplier/coupon/page 200 OK 真数据, 老字段:
* - 搜索: 优惠券名 * - 搜索: 优惠券名
@ -11,6 +13,8 @@
import { ref, onMounted, reactive } from 'vue' import { ref, onMounted, reactive } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus' import { ElMessage, ElMessageBox } from 'element-plus'
import { httpGet } from '@/utils/request' import { httpGet } from '@/utils/request'
import PageHeader from '@/components/PageHeader/PageHeader.vue'
import SearchBar from '@/components/SearchBar/SearchBar.vue'
interface Coupon { interface Coupon {
id: string id: string
@ -119,28 +123,19 @@ onMounted(load)
<template> <template>
<div class="rr-page"> <div class="rr-page">
<div class="rr-page-header"> <PageHeader title="优惠券管理" :sub="`平台/企业优惠券管理 (共 ${total} 张, 选中 ${selection.length})`">
<div>
<h2 class="rr-page-title">优惠券管理</h2>
<p class="rr-page-sub">平台/企业优惠券管理 (共 {{ total }} 张, 选中 {{ selection.length }})</p>
</div>
<div class="rr-page-actions">
<el-button type="primary" @click="onAdd">新增优惠券</el-button> <el-button type="primary" @click="onAdd">新增优惠券</el-button>
<el-button type="danger" :disabled="selection.length === 0" @click="onBatchDelete">批量删除</el-button> <el-button type="danger" :disabled="selection.length === 0" @click="onBatchDelete">批量删除</el-button>
</div> </PageHeader>
</div>
<div class="rr-card rr-search"> <SearchBar
<el-form :inline="true" @keyup.enter="onSearch"> v-model:filters="filters"
<el-form-item label="优惠券名称"> :fields="[
<el-input v-model="filters.name" placeholder="请输入优惠券名称" clearable style="width: 280px" /> { key: 'name', label: '优惠券名称', type: 'text', placeholder: '请输入优惠券名称' }
</el-form-item> ]"
<el-form-item> @search="onSearch"
<el-button @click="onReset">重置</el-button> @reset="onReset"
<el-button type="primary" @click="onSearch">查询</el-button> />
</el-form-item>
</el-form>
</div>
<div class="rr-card"> <div class="rr-card">
<el-table :data="list" border style="width: 100%" v-loading="loading" :empty-text="error || '暂无优惠券'" @selection-change="onSelectionChange" row-key="id"> <el-table :data="list" border style="width: 100%" v-loading="loading" :empty-text="error || '暂无优惠券'" @selection-change="onSelectionChange" row-key="id">
@ -219,15 +214,5 @@ onMounted(load)
</template> </template>
<style scoped lang="scss"> <style scoped lang="scss">
.rr-page { max-width: 1500px; } .rr-page { max-width: 1400px; }
.rr-page-header { margin-bottom: 16px; display: flex; justify-content: space-between; align-items: flex-start; }
.rr-page-title { font-size: 22px; font-weight: 600; color: var(--ink); margin: 0 0 4px 0; }
.rr-page-sub { color: var(--ink-3); font-size: 13px; margin: 0; }
.rr-page-actions { display: flex; gap: 8px; }
.rr-card { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-lg); overflow: hidden; margin-bottom: 16px; }
.rr-search { padding: 16px 20px; }
.rr-pagination { padding: 12px 20px; display: flex; justify-content: flex-end; border-top: 1px solid var(--border); }
.rr-muted { color: var(--ink-3); }
.rr-stock-ok { color: var(--primary); font-weight: 600; }
.rr-stock-out { color: var(--ink-3); }
</style> </style>

View File

@ -1,6 +1,8 @@
<script setup lang="ts"> <script setup lang="ts">
/** /**
* F006 企业管理 — 套 UserListView 模式 + v2.0 设计规范 * F006 企业管理 - W10 A5 标准化
*
* W10 A5: 套 PageHeader/SearchBar 标准化模板
* *
* 后端端点 (ApiEnterpriseController @ /user/enterprise): * 后端端点 (ApiEnterpriseController @ /user/enterprise):
* GET /user/enterprise/page 分页列表 * GET /user/enterprise/page 分页列表
@ -10,6 +12,8 @@ import { onMounted, ref, reactive } from 'vue'
import { ElMessage } from 'element-plus' import { ElMessage } from 'element-plus'
import { httpGet } from '@/utils/request' import { httpGet } from '@/utils/request'
import DataTable from '@/components/DataTable/DataTable.vue' import DataTable from '@/components/DataTable/DataTable.vue'
import PageHeader from '@/components/PageHeader/PageHeader.vue'
import SearchBar from '@/components/SearchBar/SearchBar.vue'
interface Enterprise { interface Enterprise {
id: string id: string
@ -103,24 +107,20 @@ onMounted(() => { load() })
<template> <template>
<div class="rr-sys-user"> <div class="rr-sys-user">
<div class="rr-page-header"> <PageHeader title="企业管理" :sub="`共 ${total} 家企业`" />
<div class="rr-page-titles">
<h2 class="rr-page-title">企业管理</h2>
<p class="rr-page-sub">共 {{ total }} 家企业</p>
</div>
<div class="rr-page-actions">
<el-button @click="onReset" class="rr-btn-secondary">重置</el-button>
</div>
</div>
<div class="rr-filters-row"> <SearchBar
<el-input v-model="filters.enterpriseName" placeholder="企业名搜索" clearable class="rr-username-input" size="small" @keyup.enter="onSearch" /> v-model:filters="filters"
<el-select v-model="filters.enterpriseType" placeholder="企业类型" class="rr-type-select" clearable size="small"> :fields="[
<el-option value="1" label="供应商" /> { key: 'enterpriseName', label: '企业名', type: 'text', placeholder: '企业名搜索' },
<el-option value="2" label="采购商" /> { key: 'enterpriseType', label: '企业类型', type: 'select', options: [
</el-select> { value: 1, label: '供应商' },
<el-button class="rr-btn-secondary" size="small" @click="onSearch">查询</el-button> { value: 2, label: '采购商' }
</div> ] }
]"
@search="onSearch"
@reset="onReset"
/>
<div class="rr-list-card"> <div class="rr-list-card">
<DataTable <DataTable
@ -186,15 +186,7 @@ onMounted(() => { load() })
<style scoped> <style scoped>
.rr-sys-user { padding: 16px; } .rr-sys-user { padding: 16px; }
.rr-page-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 14px; } .rr-list-card { background: var(--surface); border-radius: 12px; padding: 4px; }
.rr-page-titles { display: flex; flex-direction: column; gap: 2px; } .rr-time { font-family: 'SF Mono', Menlo, Monaco, Consolas, monospace; font-size: 12px; color: var(--ink-2); }
.rr-page-title { margin: 0; font-size: 18px; font-weight: 600; color: var(--el-text-color-primary); } .rr-muted { color: var(--ink-3); font-size: 12px; }
.rr-page-sub { margin: 0; font-size: 12px; color: var(--el-text-color-secondary); }
.rr-page-actions { display: flex; gap: 8px; }
.rr-filters-row { display: flex; align-items: center; gap: 8px; margin-bottom: 14px; padding: 12px 16px; background: var(--el-fill-color-light); border-radius: 8px; }
.rr-username-input { width: 240px; }
.rr-type-select { width: 140px; }
.rr-list-card { background: var(--el-bg-color); border-radius: 12px; padding: 4px; }
.rr-time { font-family: 'SF Mono', Menlo, Monaco, Consolas, monospace; font-size: 12px; color: var(--el-text-color-regular); }
.rr-muted { color: var(--el-text-color-placeholder); font-size: 12px; }
</style> </style>

View File

@ -1,6 +1,8 @@
<script setup lang="ts"> <script setup lang="ts">
/** /**
* F006 财务管理 — 余额明细 * F006 财务管理 (余额明细) - W10 A5 标准化
*
* W10 A5: 套 PageHeader/SearchBar 标准化模板
* *
* 后端端点 (BalanceDetailController @ /user/balancedetail): * 后端端点 (BalanceDetailController @ /user/balancedetail):
* GET /user/balancedetail/page 分页列表 * GET /user/balancedetail/page 分页列表
@ -9,6 +11,8 @@
import { onMounted, ref, reactive } from 'vue' import { onMounted, ref, reactive } from 'vue'
import { httpGet } from '@/utils/request' import { httpGet } from '@/utils/request'
import DataTable from '@/components/DataTable/DataTable.vue' import DataTable from '@/components/DataTable/DataTable.vue'
import PageHeader from '@/components/PageHeader/PageHeader.vue'
import SearchBar from '@/components/SearchBar/SearchBar.vue'
interface BalanceDetail { interface BalanceDetail {
id: string id: string
@ -99,25 +103,21 @@ onMounted(() => { load() })
<template> <template>
<div class="rr-sys-user"> <div class="rr-sys-user">
<div class="rr-page-header"> <PageHeader title="财务管理" :sub="`共 ${total} 条明细`" />
<div class="rr-page-titles">
<h2 class="rr-page-title">财务管理</h2>
<p class="rr-page-sub">共 {{ total }} 条明细</p>
</div>
<div class="rr-page-actions">
<el-button @click="onReset" class="rr-btn-secondary">重置</el-button>
</div>
</div>
<div class="rr-filters-row"> <SearchBar
<el-select v-model="filters.type" placeholder="类型筛选" class="rr-type-select" clearable size="small"> v-model:filters="filters"
<el-option value="1" label="收入" /> :fields="[
<el-option value="2" label="支出" /> { key: 'type', label: '类型', type: 'select', options: [
<el-option value="3" label="提现" /> { value: 1, label: '收入' },
<el-option value="4" label="冻结" /> { value: 2, label: '支出' },
</el-select> { value: 3, label: '提现' },
<el-button class="rr-btn-secondary" size="small" @click="onSearch">查询</el-button> { value: 4, label: '冻结' }
</div> ] }
]"
@search="onSearch"
@reset="onReset"
/>
<div class="rr-list-card"> <div class="rr-list-card">
<DataTable <DataTable
@ -164,15 +164,8 @@ onMounted(() => { load() })
<style scoped> <style scoped>
.rr-sys-user { padding: 16px; } .rr-sys-user { padding: 16px; }
.rr-page-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 14px; } .rr-list-card { background: var(--surface); border-radius: 12px; padding: 4px; }
.rr-page-titles { display: flex; flex-direction: column; gap: 2px; } .rr-money { font-family: 'SF Mono', Menlo, Monaco, Consolas, monospace; font-size: 13px; font-weight: 500; color: var(--ink); }
.rr-page-title { margin: 0; font-size: 18px; font-weight: 600; color: var(--el-text-color-primary); } .rr-time { font-family: 'SF Mono', Menlo, Monaco, Consolas, monospace; font-size: 12px; color: var(--ink-2); }
.rr-page-sub { margin: 0; font-size: 12px; color: var(--el-text-color-secondary); } .rr-muted { color: var(--ink-3); font-size: 12px; }
.rr-page-actions { display: flex; gap: 8px; }
.rr-filters-row { display: flex; align-items: center; gap: 8px; margin-bottom: 14px; padding: 12px 16px; background: var(--el-fill-color-light); border-radius: 8px; }
.rr-type-select { width: 140px; }
.rr-list-card { background: var(--el-bg-color); border-radius: 12px; padding: 4px; }
.rr-money { font-family: 'SF Mono', Menlo, Monaco, Consolas, monospace; font-size: 13px; font-weight: 500; color: var(--el-text-color-primary); }
.rr-time { font-family: 'SF Mono', Menlo, Monaco, Consolas, monospace; font-size: 12px; color: var(--el-text-color-regular); }
.rr-muted { color: var(--el-text-color-placeholder); font-size: 12px; }
</style> </style>

View File

@ -1,6 +1,8 @@
<script setup lang="ts"> <script setup lang="ts">
/** /**
* F006 用户管理 (前台用户列表) - W3.x C P0.3 * F006 用户管理 (前台用户列表) - W10 A5 标准化
*
* W10 A5: 套 PageHeader/SearchBar 标准化模板
* 走 /user/user/page 后端 * 走 /user/user/page 后端
* *
* 字段 (从 API 实测): * 字段 (从 API 实测):
@ -12,6 +14,8 @@
import { onMounted, ref, reactive } from 'vue' import { onMounted, ref, reactive } from 'vue'
import { httpGet } from '@/utils/request' import { httpGet } from '@/utils/request'
import DataTable from '@/components/DataTable/DataTable.vue' import DataTable from '@/components/DataTable/DataTable.vue'
import PageHeader from '@/components/PageHeader/PageHeader.vue'
import SearchBar from '@/components/SearchBar/SearchBar.vue'
interface FrontUser { interface FrontUser {
id: string id: string
@ -75,18 +79,18 @@ onMounted(load)
<template> <template>
<div class="rr-page"> <div class="rr-page">
<div class="rr-page-header"> <PageHeader title="用户列表" :sub="`前台注册用户 (共 ${total} 个)`" />
<div>
<h2 class="rr-page-title">用户列表</h2> <SearchBar
<p class="rr-page-sub">前台注册用户(共 {{ total }} 个)</p> v-model:filters="query"
</div> :fields="[
</div> { key: 'keyword', label: '搜索', type: 'text', placeholder: '搜索手机号/昵称' }
]"
@search="onSearch"
@reset="onSearch"
/>
<div class="rr-card"> <div class="rr-card">
<div class="rr-toolbar">
<el-input v-model="query.keyword" placeholder="搜索手机号/昵称" clearable style="width: 280px;" @keyup.enter="onSearch" />
<el-button type="primary" :icon="'Search'" @click="onSearch">搜索</el-button>
</div>
<DataTable <DataTable
:columns="columns" :columns="columns"
:data="list" :data="list"
@ -105,9 +109,5 @@ onMounted(load)
<style scoped lang="scss"> <style scoped lang="scss">
.rr-page { max-width: 1400px; } .rr-page { max-width: 1400px; }
.rr-page-header { margin-bottom: 20px; } .user-header { width: 32px; height: 32px; border-radius: 50%; vertical-align: middle; }
.rr-page-title { font-size: 22px; font-weight: 600; letter-spacing: -0.02em; color: var(--ink); margin-bottom: 4px; }
.rr-page-sub { color: var(--ink-3); font-size: 13px; }
.rr-card { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-lg); overflow: hidden; }
.rr-toolbar { display: flex; align-items: center; gap: 8px; padding: 14px 20px; border-bottom: 1px solid var(--border); }
</style> </style>