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

Merged
direv merged 85 commits from develop into main 2026-08-07 11:27:17 +08:00
38 changed files with 130 additions and 239 deletions
Showing only changes of commit 4b77d67dc2 - Show all commits

View File

@ -116,7 +116,7 @@ onMounted(load)
:total="total"
:page="page"
:limit="limit"
:show-pagination="total > 10"
:show-pagination="total > 10" :page-sizes="[10, 20, 50, 100]"
:error="error"
empty-text="暂无反馈"
borderless

View File

@ -115,7 +115,7 @@ onMounted(load)
:total="total"
:page="page"
:limit="limit"
:show-pagination="total > 10"
:show-pagination="total > 10" :page-sizes="[10, 20, 50, 100]"
:error="error"
empty-text="暂无帮助文档"
borderless

View File

@ -137,7 +137,7 @@ onMounted(load)
:total="total"
:page="page"
:limit="limit"
:show-pagination="total > 10"
:show-pagination="total > 10" :page-sizes="[10, 20, 50, 100]"
:error="error"
empty-text="暂无轮播图"
borderless

View File

@ -7,12 +7,13 @@
*
* 设计规范:§16 列表页完整模板 + §17.7 紧凑弹窗 + §17.8 主题色弹窗 + §17.9 列优化
*/
import { onMounted, computed, ref } from 'vue'
import { onMounted, computed, reactive, ref } from 'vue'
import { useRouter } from 'vue-router'
import { ElMessage } from 'element-plus'
import DataTable from '@/components/DataTable/DataTable.vue'
import PageHeader from '@/components/PageHeader/PageHeader.vue'
import SearchBar from '@/components/SearchBar/SearchBar.vue'
import ListTabs from '@/components/ListTabs/ListTabs.vue'
import { useInquiryStore, STATUS_OPTIONS } from '@/stores/inquiry'
import { httpGet } from '@/utils/request'
@ -29,7 +30,10 @@ interface InquiryRow {
const router = useRouter()
const store = useInquiryStore()
const STATUS_TABS = STATUS_OPTIONS.map(o => ({ value: o.value, label: o.label }))
const STATUS_TABS = STATUS_OPTIONS.map(o => ({ value: o.value, label: o.label, key: o.value, count: 0 }))
// 各 status 计数 (在当前结果中累加)
const stats = reactive<Record<string, number>>({ pending: 0, quoting: 0, done: 0, cancelled: 0, all: 0 })
const STATUS_LABEL: Record<string, string> = {
pending: '待报价',
@ -86,6 +90,9 @@ async function load() {
raw: it
}))
total.value = arr.length + (page.value - 1) * limit.value
// 各状态计数 (基于当前页结果)
stats.all = list.value.length
list.value.forEach(r => { stats[r.status] = (stats[r.status] || 0) + 1 })
} catch (e: any) {
error.value = e?.msg || e?.message || '后端接口异常(详见 console)'
list.value = []
@ -96,6 +103,12 @@ async function load() {
}
function onSearch() { page.value = 1; load() }
const tabItems = computed(() => STATUS_TABS.map(t => ({
key: t.value,
label: t.label,
count: t.value === '' ? stats.all : (stats[t.value] || 0)
})))
function onReset() { filters.value.status = ''; filters.value.customer = ''; filters.value.searchKey = ''; page.value = 1; load() }
function onPageChange(p: number) { page.value = p; load() }
function onLimitChange(l: number) { limit.value = l; page.value = 1; load() }
@ -126,17 +139,7 @@ onMounted(() => { load() })
<el-button @click="onReset">重置</el-button>
</PageHeader>
<div class="rr-tabs-row">
<div class="rr-tabs">
<div
v-for="t in STATUS_TABS"
:key="t.value"
class="rr-tab"
:class="{ active: filters.status === t.value }"
@click="onStatusTab(t.value)"
>{{ t.label }}</div>
</div>
</div>
<ListTabs v-model="filters.status" :items="tabItems" @change="onStatusTab" />
<SearchBar
v-model:filters="filters"
@ -153,7 +156,7 @@ onMounted(() => { load() })
:total="total"
:page="page"
:limit="limit"
:show-pagination="true"
:show-pagination="true" :page-sizes="[10, 20, 50, 100]"
:error="error"
empty-text="暂无询价"
borderless
@ -181,52 +184,6 @@ onMounted(() => { load() })
padding: 16px;
}
.rr-tabs-row {
display: flex;
align-items: center;
justify-content: flex-start;
margin-bottom: 12px;
gap: 16px;
}
.rr-tabs {
display: flex;
gap: 24px;
flex: 1;
}
.rr-tab {
position: relative;
padding: 6px 0;
font-size: 13px;
font-weight: 500;
color: var(--el-text-color-secondary);
cursor: pointer;
user-select: none;
transition: color 0.15s ease;
}
.rr-tab:hover { color: var(--el-text-color-primary); }
.rr-tab.active {
color: var(--el-color-primary);
font-weight: 600;
}
.rr-tab.active::after {
content: '';
position: absolute;
bottom: 0;
left: 0;
right: 0;
height: 2px;
background: var(--el-color-primary);
border-radius: 1px;
}
.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;

View File

@ -345,7 +345,7 @@ onMounted(() => {
:total="total"
:page="page"
:limit="limit"
:show-pagination="true"
:show-pagination="true" :page-sizes="[10, 20, 50, 100]"
:error="loadError"
empty-text="暂无审计记录"
borderless

View File

@ -268,12 +268,12 @@ onMounted(() => { load(); loadCustomers() })
{ prop: 'createDate', label: '创建时间', width: 170, slot: 'createDate' },
{ label: '操作', width: 280, slot: 'action' }
]"
:data="list"
:data="list" :borderless="true"
:loading="loading"
:total="total"
:page="page"
:limit="limit"
:show-pagination="true"
:show-pagination="true" :page-sizes="[10, 20, 50, 100]"
:error="loadError"
empty-text="暂无公司账号数据"
row-key="id"

View File

@ -17,10 +17,11 @@
*/
import { ref, onMounted, reactive, computed } from 'vue'
import { useRouter, useRoute } from 'vue-router'
import { ElMessage } from 'element-plus'
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'
import ListTabs from '@/components/ListTabs/ListTabs.vue'
import DataTable from '@/components/DataTable/DataTable.vue'
interface Order {
@ -82,6 +83,25 @@ const filters = reactive({
endDate: ''
})
const selection = ref<Order[]>([])
const columns: any = computed(() => [
{ type: 'selection', label: '', width: 50 },
{ prop: 'orderNo', label: '订单号', width: 180 },
{ prop: 'contractCode', label: '合同号', width: 160, slot: 'contractCode' },
{ prop: 'enterpriseName', label: '供应商', minWidth: 180, slot: 'enterpriseName' },
{ prop: 'orderUserName', label: '采购方', minWidth: 160, slot: 'orderUserName' },
{ prop: 'totalAmount', label: '金额', width: 130, align: 'right', slot: 'amount' },
{ prop: 'totalNum', label: '数量', width: 80, align: 'center' },
{ prop: 'shippedNum', label: '已发', width: 80, align: 'center' },
{ prop: 'status', label: '状态', width: 110, align: 'center', slot: 'status' },
{ prop: 'createDate', label: '下单时间', width: 170, slot: 'time' },
{ label: '操作', width: 280, align: 'center', slot: 'action' }
])
const tabItems = computed(() => STATUS_TABS.map(t => ({
key: t.value,
label: t.label,
count: t.value === '' ? stats.all : (stats[Number(t.value)] || 0)
})))
const stats = reactive<Record<number|string, number>>({ 0: 0, 1: 0, 2: 0, 3: 0, 4: 0, 5: 0, 6: 0, 7: 0, 8: 0, 9: 0, all: 0 })
const router = useRouter()
const route = useRoute()
@ -127,6 +147,10 @@ async function load() {
// 后端 total 是字符串 "1356", parseInt 兜底
const t = r?.total
total.value = typeof t === 'string' ? parseInt(t, 10) : (Number(t) || 0)
// 各 status 计数
Object.keys(stats).forEach(k => (stats as any)[k] = 0)
stats.all = rows.length
rows.forEach(r => { stats[r.status] = ((stats[r.status] as number) || 0) + 1 })
} catch (e: any) {
error.value = e?.msg || e?.message || '加载失败'
list.value = FALLBACK
@ -183,26 +207,13 @@ onMounted(load)
<template>
<div class="rr-page">
<PageHeader title="订单管理" :sub="`共 ${total} 条, 选中 ${selection.length}`">
<PageHeader title="订单管理" :sub="`共 ${total} 条订单${selection.length ? `, 已选 ${selection.length}` : ''}`">
<el-button v-if="selection.length > 0" type="primary" @click="onExportSelected">
导出选中 ({{ selection.length }})
</el-button>
</PageHeader>
<!-- 状态 tab -->
<div class="rr-tabs-row">
<div class="rr-tabs">
<div
v-for="tab in STATUS_TABS"
:key="tab.value"
class="rr-tab"
:class="{ active: filters.status === tab.value }"
@click="onStatusTabChange(tab.value)"
>
{{ tab.label }}
</div>
</div>
</div>
<ListTabs v-model="filters.status" :items="tabItems" @change="onStatusTabChange" />
<SearchBar
v-model:filters="filters"
@ -217,30 +228,18 @@ onMounted(load)
@reset="onReset"
/>
<div class="rr-card">
<DataTable
:columns="[
{ type: 'selection', label: '', width: 50 },
{ prop: 'orderNo', label: '订单号', width: 180 },
{ prop: 'contractCode', label: '合同号', width: 160, slot: 'contractCode' },
{ prop: 'enterpriseName', label: '供应商', minWidth: 180, slot: 'enterpriseName' },
{ prop: 'orderUserName', label: '采购方', minWidth: 160, slot: 'orderUserName' },
{ prop: 'totalAmount', label: '金额', width: 130, align: 'right', slot: 'amount' },
{ prop: 'totalNum', label: '数量', width: 80, align: 'center' },
{ prop: 'shippedNum', label: '已发', width: 80, align: 'center' },
{ prop: 'status', label: '状态', width: 110, align: 'center', slot: 'status' },
{ prop: 'createDate', label: '下单时间', width: 170, slot: 'time' },
{ label: '操作', width: 280, align: 'center', slot: 'action' }
]"
:columns="columns"
:data="list"
:loading="loading"
:total="total"
:page="page"
:limit="limit"
:show-pagination="total > 10"
:page-sizes="[10, 20, 50, 100]"
:show-pagination="true"
:error="error"
empty-text="暂无订单"
borderless
:borderless="true"
row-key="id"
@page-change="onPageChange"
@limit-change="onLimitChange"
@ -274,28 +273,39 @@ onMounted(load)
</el-tag>
</template>
<template #action="{ row }">
<el-button text type="primary" size="small" @click="onViewDetail(row)">详情</el-button>
<el-button v-if="row.status === 1" text type="primary" size="small" @click="onPay(row)">付款</el-button>
<el-button v-if="row.status === 2" text type="primary" size="small" @click="onShip(row)">发货</el-button>
<el-button v-if="row.status === 3" text type="primary" size="small" @click="onConfirmReceipt(row)">收货</el-button>
<el-button v-if="[1,2,3,4].includes(row.status)" text type="warning" size="small" @click="onRefund(row)">退款</el-button>
<el-button v-if="[1,2].includes(row.status)" text type="danger" size="small" @click="onCancel(row)">取消</el-button>
<el-button text size="small" @click="onPrint(row)">打印</el-button>
<span class="rr-actions">
<el-link type="primary" :underline="false" @click="onViewDetail(row)">详情</el-link>
<span class="rr-actions__sep">|</span>
<el-link v-if="row.status === 1" type="primary" :underline="false" @click="onPay(row)">付款</el-link>
<el-link v-else-if="row.status === 2" type="primary" :underline="false" @click="onShip(row)">发货</el-link>
<el-link v-else-if="row.status === 3" type="primary" :underline="false" @click="onConfirmReceipt(row)">收货</el-link>
<el-link v-else-if="[1,2,3,4].includes(row.status)" type="warning" :underline="false" @click="onRefund(row)">退款</el-link>
<span v-if="[1,2].includes(row.status)" class="rr-actions__sep">|</span>
<el-link v-if="[1,2].includes(row.status)" type="danger" :underline="false" @click="onCancel(row)">取消</el-link>
<span class="rr-actions__sep">|</span>
<el-link :underline="false" @click="onPrint(row)">打印</el-link>
</span>
</template>
</DataTable>
</div>
</div>
</template>
<style scoped lang="scss">
.rr-page { max-width: 1500px; }
.rr-tabs-row { margin-bottom: 16px; }
.rr-tabs { display: flex; gap: 4px; padding: 4px; background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-lg); width: fit-content; flex-wrap: wrap; }
.rr-tab { padding: 6px 16px; border-radius: var(--radius); font-size: 13px; color: var(--ink-2); cursor: pointer; transition: all 0.15s; }
.rr-tab:hover { background: var(--bg-soft); }
.rr-tab.active { color: white; background: var(--primary); font-weight: 500; }
.rr-card { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-lg); overflow: hidden; }
.rr-muted { color: var(--ink-3); }
.rr-actions {
display: inline-flex;
align-items: center;
gap: 0;
&__sep {
color: var(--rr-border-color, #E2E8F0);
margin: 0 8px;
font-size: 12px;
}
:deep(.el-link) {
font-size: 13px;
}
}
.rr-amount { font-weight: 600; color: var(--primary); }
.rr-time { font-family: 'SF Mono', Menlo, Monaco, Consolas, monospace; font-size: 12px; color: var(--ink-2); }
</style>

View File

@ -98,7 +98,7 @@ onMounted(load)
:total="filtered.length"
:page="1"
:limit="filtered.length || 1"
:show-pagination="list.length > 20"
:show-pagination="list.length > 20" :page-sizes="[10, 20, 50, 100]"
:error="error"
empty-text="暂无单位"
borderless

View File

@ -133,7 +133,7 @@ onMounted(load)
:total="total"
:page="page"
:limit="limit"
:show-pagination="total > 10"
:show-pagination="total > 10" :page-sizes="[10, 20, 50, 100]"
:error="error"
empty-text="暂无标签"
borderless

View File

@ -23,7 +23,7 @@ interface Guide {
const list = ref<Guide[]>([])
const total = ref(0)
const loading = ref(false)
const query = reactive({ page: 1, limit: 20 })
const query = reactive({ page: 1, limit: 10 })
const columns = [
{ prop: 'id', label: 'ID', width: 80 },
@ -49,7 +49,8 @@ onMounted(load)
<div class="rr-page">
<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"
<DataTable :columns="columns" :data="list"
:borderless="true" :loading="loading" :total="total" :page="query.page" :limit="query.limit" :show-pagination="true" row-key="id" empty-text="暂无内容" @page-change="onPageChange"
@limit-change="onLimitChange" />
</div>
</div>

View File

@ -129,7 +129,7 @@ onMounted(load)
:total="total"
:page="page"
:limit="limit"
:show-pagination="total > 10"
:show-pagination="total > 10" :page-sizes="[10, 20, 50, 100]"
:error="error"
empty-text="暂无常量"
borderless

View File

@ -1,86 +0,0 @@
<script setup lang="ts">
/**
* F006 商品店铺 - W3.x C P2
* 后端 /product/shop/page 端点状态: 404 / 400 (端点不存在或参数错)
* 走 el-result 优雅占位 + 展示参考老 /vue 后台的预期字段
*/
import { onMounted, ref } from 'vue'
import { httpGet } from '@/utils/request'
interface FieldSpec { key: string; label: string; desc: string }
const status = ref<'checking' | '404' | '200' | 'error'>('checking')
const errorMsg = ref('')
const expectedFields: FieldSpec[] = [
{ key: 'icon', label: '封面', desc: '图片缩略图' },
{ key: 'title', label: '商品名称', desc: '商品标题' },
{ key: 'enterpriseName', label: '供应商', desc: '所属企业名' },
{ key: 'firstCategoryName', label: '一级分类', desc: '一级分类名' },
{ key: 'secondCategoryName', label: '二级分类', desc: '二级分类名' },
{ key: 'thirdCategoryName', label: '三级分类', desc: '三级分类名' },
{ key: 'brandName', label: '品牌', desc: '品牌名' },
{ key: 'unitName', label: '单位', desc: '计量单位' },
{ key: 'createDate', label: '申请时间', desc: '提交时间' },
{ key: 'onShelf', label: '铺货', desc: '0=未铺货/1=已铺货' },
{ key: 'checkOpinion', label: '审核意见', desc: '审核备注' },
{ key: 'checkStatus', label: '状态', desc: '1=待审核/2=出售中/3=已驳回' }
]
onMounted(async () => {
try {
const r: any = await httpGet('/product/shop/page', { page: 1, limit: 1 })
if (r?.code === 0) status.value = '200'
else { status.value = 'error'; errorMsg.value = r?.msg || '未知错误' }
} catch (e: any) {
if (e?.response?.status === 404 || e?.message?.includes('404')) {
status.value = '404'
errorMsg.value = '后端 API 未实现 (/product/shop/page 返回 404)'
} else {
status.value = 'error'
errorMsg.value = e?.msg || e?.message || '请求失败'
}
}
})
</script>
<template>
<div class="rr-page">
<div class="rr-page-header">
<h2 class="rr-page-title">商品店铺</h2>
<p class="rr-page-sub">商品管理 (supplier/good 同款) - 数据接口未实现, 占位页展示预期字段</p>
</div>
<div class="rr-card rr-status-card">
<el-result
:icon="status === '200' ? 'success' : 'warning'"
:title="status === '200' ? 'API 已就绪' : '后端 API 未实现'"
:sub-title="status === '200' ? '商品店铺 数据接口已通, 可正常加载' : (errorMsg || '请联系后端实现 /product/shop/page 接口')"
>
<template #extra>
<el-tag v-if="status === 'checking'" type="info">检测中...</el-tag>
<el-tag v-else-if="status === '404'" type="warning">404 Not Found</el-tag>
<el-tag v-else-if="status === '200'" type="success">200 OK</el-tag>
<el-tag v-else type="danger">Error</el-tag>
</template>
</el-result>
</div>
<div class="rr-card rr-fields-card">
<h3 class="rr-section-title">预期字段 (参考老 /vue 后台)</h3>
<el-table :data="expectedFields" border size="small" :show-header="true" empty-text="无字段">
<el-table-column prop="key" label="字段名 (key)" width="220" />
<el-table-column prop="label" label="表头 (label)" width="180" />
<el-table-column prop="desc" label="说明" />
</el-table>
</div>
</div>
</template>
<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); padding: 24px; margin-bottom: 16px; }
.rr-status-card { padding: 20px 20px 8px; }
.rr-section-title { margin: 0 0 12px; font-size: 14px; font-weight: 600; color: var(--ink); }
</style>

View File

@ -128,12 +128,12 @@ onMounted(() => { load() })
{ prop: 'endTime', label: '结束时间', width: 170, slot: 'endTime' },
{ label: '操作', width: 100, slot: 'action' }
]"
:data="list"
:data="list" :borderless="true"
:loading="loading"
:total="total"
:page="page"
:limit="limit"
:show-pagination="true"
:show-pagination="true" :page-sizes="[10, 20, 50, 100]"
:error="loadError"
empty-text="暂无活动"
row-key="id"

View File

@ -90,7 +90,8 @@ onMounted(load)
<el-tab-pane v-for="t in STATUS_DEFAULTS" :key="t.value" :name="t.value" :label="t.label" />
</el-tabs>
<SearchBar v-model:filters="filters" :fields="searchFields" @search="onSearch" />
<DataTable :columns="columns" :data="filtered" :loading="loading" :page="page" :limit="limit" :total="total" row-key="id"
<DataTable :columns="columns" :data="filtered"
:borderless="true" :loading="loading" :page="page" :limit="limit" :total="total" row-key="id"
@page-change="(p: number) => { page = p; load() }" @limit-change="(l: number) => { limit = l; page = 1; load() }">
<template #couponId="{ row }">
<el-link v-if="row.couponId" type="primary" :underline="false" @click="onView(row)">{{ row.couponId }}</el-link>

View File

@ -93,7 +93,8 @@ onMounted(load)
<el-tab-pane v-for="t in STATUS_DEFAULTS" :key="t.value" :name="t.value" :label="t.label" />
</el-tabs>
<SearchBar v-model:filters="filters" :fields="searchFields" @search="onSearch" />
<DataTable :columns="columns" :data="filtered" :loading="loading" :page="page" :limit="limit" :total="total" row-key="id"
<DataTable :columns="columns" :data="filtered"
:borderless="true" :loading="loading" :page="page" :limit="limit" :total="total" row-key="id"
@page-change="(p: number) => { page = p; load() }" @limit-change="(l: number) => { limit = l; page = 1; load() }">
<template #userType="{ row }">
<el-tag :type="row.userType === 1 ? 'primary' : 'success'" size="small">{{ row.userType === 1 ? 'C端用户' : '供应商' }}</el-tag>

View File

@ -100,7 +100,8 @@ onMounted(load)
<el-tab-pane v-for="t in STATUS_DEFAULTS" :key="t.value" :name="t.value" :label="t.label" />
</el-tabs>
<SearchBar v-model:filters="filters" :fields="searchFields" @search="onSearch" />
<DataTable :columns="columns" :data="filtered" :loading="loading" :page="page" :limit="limit" :total="total" row-key="id"
<DataTable :columns="columns" :data="filtered"
:borderless="true" :loading="loading" :page="page" :limit="limit" :total="total" row-key="id"
@page-change="(p: number) => { page = p; load() }" @limit-change="(l: number) => { limit = l; page = 1; load() }">
<template #time="{ row }">{{ row.createDate }}</template>
<template #actions="{ row }">

View File

@ -98,7 +98,8 @@ onMounted(load)
<el-tab-pane v-for="t in STATUS_DEFAULTS" :key="t.value" :name="t.value" :label="t.label" />
</el-tabs>
<SearchBar v-model:filters="filters" :fields="searchFields" @search="onSearch" />
<DataTable :columns="columns" :data="filtered" :loading="loading" :page="page" :limit="limit" :total="total" row-key="id"
<DataTable :columns="columns" :data="filtered"
:borderless="true" :loading="loading" :page="page" :limit="limit" :total="total" row-key="id"
@page-change="(p: number) => { page = p; load() }" @limit-change="(l: number) => { limit = l; page = 1; load() }">
<template #star="{ row }">
<el-rate v-model="row.star" :max="5" disabled />

View File

@ -95,7 +95,8 @@ onMounted(load)
<el-tab-pane v-for="t in STATUS_DEFAULTS" :key="t.value" :name="t.value" :label="t.label" />
</el-tabs>
<SearchBar v-model:filters="filters" :fields="searchFields" @search="onSearch" />
<DataTable :columns="columns" :data="filtered" :loading="loading" :page="page" :limit="limit" :total="total" row-key="id"
<DataTable :columns="columns" :data="filtered"
:borderless="true" :loading="loading" :page="page" :limit="limit" :total="total" row-key="id"
@page-change="(p: number) => { page = p; load() }" @limit-change="(l: number) => { limit = l; page = 1; load() }">
<template #radio="{ row }">{{ (row.promoterRadio * 100).toFixed(1) }}%</template>
<template #date1="{ row }">{{ row.beginTime }}</template>

View File

@ -167,6 +167,7 @@ onMounted(load)
:page="1"
:limit="999"
:show-pagination="false"
:page-sizes="[10, 20, 50, 100]"
:error="error"
empty-text="暂无部门"
borderless

View File

@ -172,7 +172,7 @@ onMounted(load)
:total="total"
:page="page"
:limit="limit"
:show-pagination="true"
:show-pagination="true" :page-sizes="[10, 20, 50, 100]"
:error="error"
empty-text="暂无字典数据"
borderless

View File

@ -162,7 +162,7 @@ onMounted(load)
:total="total"
:page="page"
:limit="limit"
:show-pagination="true"
:show-pagination="true" :page-sizes="[10, 20, 50, 100]"
:error="error"
empty-text="暂无字典类型"
borderless

View File

@ -108,6 +108,7 @@ onMounted(load)
:page="page"
:limit="limit"
:show-pagination="true"
:page-sizes="[10, 20, 50, 100]"
:error="error"
empty-text="暂无文件"
borderless

View File

@ -193,6 +193,7 @@ onMounted(load)
:page="1"
:limit="999"
:show-pagination="false"
:page-sizes="[10, 20, 50, 100]"
:error="error"
empty-text="暂无菜单"
borderless

View File

@ -188,7 +188,7 @@ onMounted(load)
:total="total"
:page="page"
:limit="limit"
:show-pagination="true"
:show-pagination="true" :page-sizes="[10, 20, 50, 100]"
:error="error"
empty-text="暂无公告"
borderless

View File

@ -234,12 +234,12 @@ onMounted(() => {
{ prop: 'updateDate', label: '更新时间', width: 170, slot: 'updateDate' },
{ label: '操作', width: 180, slot: 'action' }
]"
:data="list"
:data="list" :borderless="true"
:loading="loading"
:total="total"
:page="page"
:limit="limit"
:show-pagination="true"
:show-pagination="true" :page-sizes="[10, 20, 50, 100]"
:error="loadError"
empty-text="暂无参数"
row-key="id"

View File

@ -161,7 +161,7 @@ onMounted(load)
:total="total"
:page="page"
:limit="limit"
:show-pagination="true"
:show-pagination="true" :page-sizes="[10, 20, 50, 100]"
:error="error"
empty-text="暂无岗位"
borderless

View File

@ -187,7 +187,7 @@ onMounted(load)
:total="total"
:page="page"
:limit="limit"
:show-pagination="true"
:show-pagination="true" :page-sizes="[10, 20, 50, 100]"
:error="error"
empty-text="暂无商品"
borderless

View File

@ -142,7 +142,7 @@ onMounted(load)
:total="total"
:page="page"
:limit="limit"
:show-pagination="true"
:show-pagination="true" :page-sizes="[10, 20, 50, 100]"
:error="error"
empty-text="暂无角色组"
borderless

View File

@ -204,12 +204,12 @@ onMounted(() => { load() })
{ prop: 'createDate', label: '创建时间', width: 170, slot: 'createDate' },
{ label: '操作', width: 180, slot: 'action' }
]"
:data="list"
:data="list" :borderless="true"
:loading="loading"
:total="total"
:page="page"
:limit="limit"
:show-pagination="true"
:show-pagination="true" :page-sizes="[10, 20, 50, 100]"
:error="loadError"
empty-text="暂无角色"
row-key="id"

View File

@ -155,7 +155,7 @@ onMounted(load)
:total="total"
:page="page"
:limit="limit"
:show-pagination="true"
:show-pagination="true" :page-sizes="[10, 20, 50, 100]"
:error="error"
empty-text="暂无定时任务"
borderless

View File

@ -254,12 +254,12 @@ onMounted(() => { load() })
{ prop: 'createDate', label: '创建时间', width: 170, slot: 'createDate' },
{ label: '操作', width: 260, slot: 'action' }
]"
:data="list"
:data="list" :borderless="true"
:loading="loading"
:total="total"
:page="page"
:limit="limit"
:show-pagination="true"
:show-pagination="true" :page-sizes="[10, 20, 50, 100]"
:error="loadError"
empty-text="暂无用户"
row-key="id"

View File

@ -134,12 +134,12 @@ onMounted(() => { load() })
{ prop: 'registerTime', label: '注册时间', width: 170, slot: 'registerTime' },
{ label: '操作', width: 100, slot: 'action' }
]"
:data="list"
:data="list" :borderless="true"
:loading="loading"
:total="total"
:page="page"
:limit="limit"
:show-pagination="true"
:show-pagination="true" :page-sizes="[10, 20, 50, 100]"
:error="loadError"
empty-text="暂无企业"
row-key="id"

View File

@ -102,7 +102,7 @@ onMounted(() => { load() })
</script>
<template>
<div class="rr-sys-user">
<div class="rr-page">
<PageHeader title="财务管理" :sub="`共 ${total} 条明细`" />
<SearchBar
@ -119,7 +119,6 @@ onMounted(() => { load() })
@reset="onReset"
/>
<div class="rr-list-card">
<DataTable
:columns="[
{ prop: 'enterpriseName', label: '企业', width: 180 },
@ -138,6 +137,8 @@ onMounted(() => { load() })
:show-pagination="true"
:error="loadError"
empty-text="暂无明细"
:borderless="true"
:page-sizes="[10, 20, 50, 100]"
row-key="id"
@page-change="onPageChange"
@limit-change="onLimitChange"
@ -159,12 +160,10 @@ onMounted(() => { load() })
</template>
</DataTable>
</div>
</div>
</template>
<style scoped>
.rr-sys-user { padding: 16px; }
.rr-list-card { background: var(--surface); border-radius: 12px; padding: 4px; }
.rr-page { max-width: 1500px; }
.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; }

View File

@ -35,7 +35,7 @@ const loading = ref(false)
const activeTab = ref('all')
const query = reactive({
page: 1,
limit: 20,
limit: 10,
userId: '',
nickName: '',
mobile: '',

View File

@ -85,7 +85,8 @@ onMounted(load)
<el-tab-pane v-for="t in STATUS_DEFAULTS" :key="t.value" :name="t.value" :label="t.label" />
</el-tabs>
<SearchBar v-model:filters="filters" :fields="searchFields" @search="onSearch" />
<DataTable :columns="columns" :data="filtered" :loading="loading" :page="page" :limit="limit" :total="total" row-key="id"
<DataTable :columns="columns" :data="filtered"
:borderless="true" :loading="loading" :page="page" :limit="limit" :total="total" row-key="id"
@page-change="(p: number) => { page = p; load() }" @limit-change="(l: number) => { limit = l; page = 1; load() }">
<template #actions="{ row }">
<el-button type="primary" link @click="onView(row)">查看</el-button>

View File

@ -91,7 +91,8 @@ onMounted(load)
<el-tab-pane v-for="t in STATUS_DEFAULTS" :key="t.value" :name="t.value" :label="t.label" />
</el-tabs>
<SearchBar v-model:filters="filters" :fields="searchFields" @search="onSearch" />
<DataTable :columns="columns" :data="filtered" :loading="loading" :page="page" :limit="limit" :total="total" row-key="id"
<DataTable :columns="columns" :data="filtered"
:borderless="true" :loading="loading" :page="page" :limit="limit" :total="total" row-key="id"
@page-change="(p: number) => { page = p; load() }" @limit-change="(l: number) => { limit = l; page = 1; load() }">
<template #level="{ row }">
<el-tag :type="row.supplierLevel.startsWith('A') ? 'success' : row.supplierLevel.startsWith('B') ? 'primary' : row.supplierLevel.startsWith('C') ? 'warning' : 'info'" size="small">{{ row.supplierLevel }}</el-tag>

View File

@ -91,7 +91,8 @@ onMounted(load)
<el-tab-pane v-for="t in STATUS_DEFAULTS" :key="t.value" :name="t.value" :label="t.label" />
</el-tabs>
<SearchBar v-model:filters="filters" :fields="searchFields" @search="onSearch" />
<DataTable :columns="columns" :data="filtered" :loading="loading" :page="page" :limit="limit" :total="total" row-key="id"
<DataTable :columns="columns" :data="filtered"
:borderless="true" :loading="loading" :page="page" :limit="limit" :total="total" row-key="id"
@page-change="(p: number) => { page = p; load() }" @limit-change="(l: number) => { limit = l; page = 1; load() }">
<template #score="{ row }">
<span style="font-weight: 600; color: var(--primary);">{{ row.score }}</span>

View File

@ -174,10 +174,9 @@ const routes: RouteRecordRaw[] = [
meta: { title: '服务商品' }
},
{
// W3.x C P2 + W17.3.7: 商品店铺后端未实现, redirect 到 supplier/good 实物商品页
path: '/product/shop',
name: 'ProductShop',
component: () => import('@/modules/product/shop/ShopListView.vue'),
meta: { title: '店铺管理' }
redirect: '/supplier/good'
},
{
path: '/message/feedback',