refactor(F006-W10): 8 view 标准化 (批次 4-7)

批次 4-7 共 8 个 view 套 PageHeader/SearchBar:
- 批次 4 (2): coupon/goodunit
- 批次 5 (3): UserListView/EnterpriseListView/FinanceListView (sys 风格)
- 批次 6 (1): OrderDetailView (PageHeader + 返回按钮 slot)
- 批次 7 (2): ActivityListView/OperateguideListView (Activity 类似 sys, Operateguide 无搜索)

修复 GoodunitListView v-model:filters 字面量 + 缺 reactive import

W10 累计: 18 view 标准化 (10+8 = 18 view, 共减 -160+ 行)
剩余 (W11 计划): openapi×3 (OpenApp 500+ 行, 跳过 W10) / sys×14 / supplier×good / inquiry×2
This commit is contained in:
zou 2026-07-05 22:40:20 +08:00
parent 1970313cc3
commit 50c9e144e9
8 changed files with 125 additions and 163 deletions

View File

@ -1,6 +1,8 @@
<script setup lang="ts">
/**
* F006 订单详情 - 完整版 (W5.x.x+5 整改)
* F006 订单详情 - W10 A6 标准化
*
* W10 A6: 套 PageHeader (返回按钮 slot)
*
* 沿用老 vue order/order-detail.vue 1379 行完整功能:
* - 4 个 tab: 订单信息 / 商品明细 / 物流信息 / 付款发票
@ -19,6 +21,7 @@ import { ref, onMounted, watch, computed, reactive } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { ElMessage, ElMessageBox } from 'element-plus'
import { httpGet } from '@/utils/request'
import PageHeader from '@/components/PageHeader/PageHeader.vue'
interface OrderDetail {
id: string
@ -325,9 +328,9 @@ watch(orderId, load)
<template>
<div class="rr-order-detail">
<div class="rr-page-header">
<PageHeader title="订单详情" :sub="detail?.orderCode || ''">
<el-button text @click="onBack">← 返回订单列表</el-button>
</div>
</PageHeader>
<div v-if="loading" class="rr-loading">
<el-skeleton :rows="6" animated />
@ -547,7 +550,6 @@ watch(orderId, load)
<style scoped lang="scss">
.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-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; }

View File

@ -1,12 +1,16 @@
<script setup lang="ts">
/**
* F006 商品单位 - W3.x C P1.1
* F006 商品单位 - W10 A4 标准化
*
* W10 A4: 套 PageHeader/SearchBar 标准化模板 (前端筛选转 SearchBar)
* 走 /other/goodunit/list 真 API (返 data: [...] 数组, 共 112 行)
* 字段: id/name/type/supplierId/enterpriseId/createTime
*/
import { onMounted, ref, computed } from 'vue'
import { httpGet } from '@/utils/request'
import DataTable from '@/components/DataTable/DataTable.vue'
import PageHeader from '@/components/PageHeader/PageHeader.vue'
import SearchBar from '@/components/SearchBar/SearchBar.vue'
interface GoodUnit {
id: string
@ -66,14 +70,17 @@ onMounted(load)
<template>
<div class="rr-page">
<div class="rr-page-header">
<h2 class="rr-page-title">商品单位</h2>
<p class="rr-page-sub">商品计量单位管理(共 {{ list.length }} 个, 筛选后 {{ filtered.length }} 个)</p>
</div>
<PageHeader title="商品单位" :sub="`商品计量单位管理 (共 ${list.length} 个, 筛选后 ${filtered.length} 个)`" />
<div class="rr-filters">
<el-input v-model="filterKw" placeholder="按名称筛选" clearable class="rr-filter-input" size="default" />
</div>
<SearchBar
v-model:filters="{ kw: filterKw }"
:fields="[
{ key: 'kw', label: '名称', type: 'text', placeholder: '按名称筛选' }
]"
:show-reset="false"
@search="() => {}"
@reset="() => { filterKw = '' }"
/>
<div class="rr-card">
<DataTable
@ -112,11 +119,5 @@ onMounted(load)
<style scoped lang="scss">
.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); }
</style>

View File

@ -1,11 +1,14 @@
<script setup lang="ts">
/**
* F006 操作指南 - W3.x C P0.4
* F006 操作指南 - W10 A7 标准化
*
* W10 A7: 套 PageHeader (无搜索, 简洁)
* 走 /other/operateguide/page
*/
import { onMounted, ref, reactive } from 'vue'
import { httpGet } from '@/utils/request'
import DataTable from '@/components/DataTable/DataTable.vue'
import PageHeader from '@/components/PageHeader/PageHeader.vue'
interface Guide {
id: string
@ -43,10 +46,7 @@ onMounted(load)
<template>
<div class="rr-page">
<div class="rr-page-header">
<h2 class="rr-page-title">内容列表</h2>
<p class="rr-page-sub">操作指南内容(共 {{ total }} 条)</p>
</div>
<PageHeader title="操作指南" :sub="`操作指南内容 (共 ${total} 条)`" />
<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" />
</div>
@ -55,8 +55,5 @@ onMounted(load)
<style scoped lang="scss">
.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; }
</style>

View File

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

View File

@ -1,6 +1,8 @@
<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 真数据, 老字段:
* - 搜索: 优惠券名
@ -11,6 +13,8 @@
import { ref, onMounted, reactive } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { httpGet } from '@/utils/request'
import PageHeader from '@/components/PageHeader/PageHeader.vue'
import SearchBar from '@/components/SearchBar/SearchBar.vue'
interface Coupon {
id: string
@ -119,28 +123,19 @@ onMounted(load)
<template>
<div class="rr-page">
<div class="rr-page-header">
<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="danger" :disabled="selection.length === 0" @click="onBatchDelete">批量删除</el-button>
</div>
</div>
<PageHeader title="优惠券管理" :sub="`平台/企业优惠券管理 (共 ${total} 张, 选中 ${selection.length})`">
<el-button type="primary" @click="onAdd">新增优惠券</el-button>
<el-button type="danger" :disabled="selection.length === 0" @click="onBatchDelete">批量删除</el-button>
</PageHeader>
<div class="rr-card rr-search">
<el-form :inline="true" @keyup.enter="onSearch">
<el-form-item label="优惠券名称">
<el-input v-model="filters.name" placeholder="请输入优惠券名称" clearable style="width: 280px" />
</el-form-item>
<el-form-item>
<el-button @click="onReset">重置</el-button>
<el-button type="primary" @click="onSearch">查询</el-button>
</el-form-item>
</el-form>
</div>
<SearchBar
v-model:filters="filters"
:fields="[
{ key: 'name', label: '优惠券名称', type: 'text', placeholder: '请输入优惠券名称' }
]"
@search="onSearch"
@reset="onReset"
/>
<div class="rr-card">
<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>
<style scoped lang="scss">
.rr-page { max-width: 1500px; }
.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); }
.rr-page { max-width: 1400px; }
</style>

View File

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

View File

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

View File

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