增加前端格式检查配置
This commit is contained in:
@@ -3,7 +3,12 @@ import { Search } from '@element-plus/icons-vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { computed, reactive, ref } from 'vue'
|
||||
|
||||
import { fetchAdminListings, type AdminListingPage, type AdminListingQuery, type Listing } from '@/features/listings'
|
||||
import {
|
||||
fetchAdminListings,
|
||||
type AdminListingPage,
|
||||
type AdminListingQuery,
|
||||
type Listing,
|
||||
} from '@/features/listings'
|
||||
import { useAdminTable } from '@/features/admin/composables/useAdminTable'
|
||||
import { useMoney } from '@/shared/composables/useMoney'
|
||||
import {
|
||||
@@ -29,7 +34,11 @@ const filters = reactive<AdminListingQuery>({
|
||||
const pageSize = ref(10)
|
||||
const currentPage = ref(1)
|
||||
|
||||
const { loading, data: listingPage, load: loadListings } = useAdminTable<AdminListingPage>({
|
||||
const {
|
||||
loading,
|
||||
data: listingPage,
|
||||
load: loadListings,
|
||||
} = useAdminTable<AdminListingPage>({
|
||||
fetchFn: () =>
|
||||
fetchAdminListings({
|
||||
...filters,
|
||||
@@ -46,9 +55,13 @@ const { loading, data: listingPage, load: loadListings } = useAdminTable<AdminLi
|
||||
|
||||
const listings = computed(() => listingPage.value.items)
|
||||
const totalListings = computed(() => listingPage.value.total)
|
||||
const publishedCount = computed(() => listings.value.filter((item) => item.status === 'published').length)
|
||||
const rentedCount = computed(() => listings.value.filter((item) => item.status === 'rented').length)
|
||||
const pendingCount = computed(() => listings.value.filter((item) => item.review_status === 'pending').length)
|
||||
const publishedCount = computed(
|
||||
() => listings.value.filter(item => item.status === 'published').length
|
||||
)
|
||||
const rentedCount = computed(() => listings.value.filter(item => item.status === 'rented').length)
|
||||
const pendingCount = computed(
|
||||
() => listings.value.filter(item => item.review_status === 'pending').length
|
||||
)
|
||||
const totalPages = computed(() => Math.max(1, Math.ceil(totalListings.value / pageSize.value)))
|
||||
|
||||
const screenshotColumns = [
|
||||
@@ -65,10 +78,18 @@ const screenshotColumns = [
|
||||
{ label: '六头', width: 50, read: (row: Listing) => resourceText(row, 'helmet6') },
|
||||
{ label: '六甲', width: 50, read: (row: Listing) => resourceText(row, 'armor6') },
|
||||
{ label: '特殊刀皮', width: 110, read: (row: Listing) => skinGroupText(row, 'melee') },
|
||||
{ label: '人物红皮/人物金皮/武器皮肤', width: 420, read: (row: Listing) => characterAndWeaponSkinText(row) },
|
||||
{
|
||||
label: '人物红皮/人物金皮/武器皮肤',
|
||||
width: 420,
|
||||
read: (row: Listing) => characterAndWeaponSkinText(row),
|
||||
},
|
||||
{ label: '租金/押金', width: 96, read: (row: Listing) => rentAndDepositText(row) },
|
||||
{ label: '比例', width: 64, read: (row: Listing) => formatRatio(row) },
|
||||
{ label: '租期', width: 92, read: (row: Listing) => `${formatEstimatedRentalDuration(row)}\n日耗 ${getDailyLoss(row)}` },
|
||||
{
|
||||
label: '租期',
|
||||
width: 92,
|
||||
read: (row: Listing) => `${formatEstimatedRentalDuration(row)}\n日耗 ${getDailyLoss(row)}`,
|
||||
},
|
||||
] as const
|
||||
|
||||
async function queryListings() {
|
||||
@@ -90,7 +111,9 @@ function setStatusFilter(status: string) {
|
||||
}
|
||||
|
||||
function setReviewStatusFilter(reviewStatus: string) {
|
||||
filters.review_status = (filters.review_status === reviewStatus ? '' : reviewStatus) as AdminListingQuery['review_status']
|
||||
filters.review_status = (
|
||||
filters.review_status === reviewStatus ? '' : reviewStatus
|
||||
) as AdminListingQuery['review_status']
|
||||
filters.status = ''
|
||||
void queryListings()
|
||||
}
|
||||
@@ -143,7 +166,7 @@ async function downloadTableScreenshot() {
|
||||
async function createTableScreenshotBlob() {
|
||||
if (!listings.value.length) throw new Error('当前页暂无可截图数据')
|
||||
const canvas = renderTableScreenshotCanvas(listings.value)
|
||||
const blob = await new Promise<Blob | null>((resolve) => canvas.toBlob(resolve, 'image/png'))
|
||||
const blob = await new Promise<Blob | null>(resolve => canvas.toBlob(resolve, 'image/png'))
|
||||
if (!blob) throw new Error('截图生成失败')
|
||||
return blob
|
||||
}
|
||||
@@ -165,14 +188,17 @@ function renderTableScreenshotCanvas(rows: Listing[]) {
|
||||
if (!measureCtx) throw new Error('截图画布初始化失败')
|
||||
measureCtx.font = '13px Arial, "Microsoft YaHei", sans-serif'
|
||||
|
||||
const rowLines = rows.map((row) =>
|
||||
screenshotColumns.map((column) => wrapCanvasText(measureCtx, column.read(row), column.width - cellPaddingX * 2)),
|
||||
const rowLines = rows.map(row =>
|
||||
screenshotColumns.map(column =>
|
||||
wrapCanvasText(measureCtx, column.read(row), column.width - cellPaddingX * 2)
|
||||
)
|
||||
)
|
||||
const rowHeights = rowLines.map((lineGroups) => {
|
||||
const maxLines = Math.max(...lineGroups.map((lines) => lines.length), 1)
|
||||
const rowHeights = rowLines.map(lineGroups => {
|
||||
const maxLines = Math.max(...lineGroups.map(lines => lines.length), 1)
|
||||
return Math.max(44, maxLines * lineHeight + cellPaddingY * 2)
|
||||
})
|
||||
const canvasHeight = paddingY * 2 + titleHeight + headerHeight + rowHeights.reduce((sum, height) => sum + height, 0)
|
||||
const canvasHeight =
|
||||
paddingY * 2 + titleHeight + headerHeight + rowHeights.reduce((sum, height) => sum + height, 0)
|
||||
const canvas = document.createElement('canvas')
|
||||
canvas.width = Math.round(canvasWidth * ratio)
|
||||
canvas.height = Math.round(canvasHeight * ratio)
|
||||
@@ -189,7 +215,11 @@ function renderTableScreenshotCanvas(rows: Listing[]) {
|
||||
ctx.fillText('商品管理', paddingX, paddingY + 20)
|
||||
ctx.fillStyle = '#8f9bba'
|
||||
ctx.font = '12px Arial, "Microsoft YaHei", sans-serif'
|
||||
ctx.fillText(`当前页 ${rows.length} 条 / 查询结果 ${totalListings.value} 条`, paddingX, paddingY + 40)
|
||||
ctx.fillText(
|
||||
`当前页 ${rows.length} 条 / 查询结果 ${totalListings.value} 条`,
|
||||
paddingX,
|
||||
paddingY + 40
|
||||
)
|
||||
|
||||
let y = paddingY + titleHeight
|
||||
drawRect(ctx, paddingX, y, tableWidth, headerHeight, '#f8f9fe')
|
||||
@@ -211,7 +241,10 @@ function renderTableScreenshotCanvas(rows: Listing[]) {
|
||||
for (const [columnIndex, column] of screenshotColumns.entries()) {
|
||||
const lines = rowLines[rowIndex]?.[columnIndex] ?? ['-']
|
||||
ctx.fillStyle = columnIndex === 0 ? '#4b5563' : '#3f4654'
|
||||
ctx.font = columnIndex === 0 ? '700 13px Arial, "Microsoft YaHei", sans-serif' : '13px Arial, "Microsoft YaHei", sans-serif'
|
||||
ctx.font =
|
||||
columnIndex === 0
|
||||
? '700 13px Arial, "Microsoft YaHei", sans-serif'
|
||||
: '13px Arial, "Microsoft YaHei", sans-serif'
|
||||
drawCellText(ctx, lines, x + cellPaddingX, y + cellPaddingY + 14, lineHeight)
|
||||
x += column.width
|
||||
}
|
||||
@@ -240,18 +273,37 @@ function wrapCanvasText(ctx: CanvasRenderingContext2D, text: string, maxWidth: n
|
||||
return lines
|
||||
}
|
||||
|
||||
function drawCellText(ctx: CanvasRenderingContext2D, lines: string[], x: number, y: number, lineHeight: number) {
|
||||
function drawCellText(
|
||||
ctx: CanvasRenderingContext2D,
|
||||
lines: string[],
|
||||
x: number,
|
||||
y: number,
|
||||
lineHeight: number
|
||||
) {
|
||||
lines.forEach((line, index) => {
|
||||
ctx.fillText(line, x, y + index * lineHeight)
|
||||
})
|
||||
}
|
||||
|
||||
function drawRect(ctx: CanvasRenderingContext2D, x: number, y: number, width: number, height: number, color: string) {
|
||||
function drawRect(
|
||||
ctx: CanvasRenderingContext2D,
|
||||
x: number,
|
||||
y: number,
|
||||
width: number,
|
||||
height: number,
|
||||
color: string
|
||||
) {
|
||||
ctx.fillStyle = color
|
||||
ctx.fillRect(x, y, width, height)
|
||||
}
|
||||
|
||||
function drawLine(ctx: CanvasRenderingContext2D, startX: number, startY: number, endX: number, endY: number) {
|
||||
function drawLine(
|
||||
ctx: CanvasRenderingContext2D,
|
||||
startX: number,
|
||||
startY: number,
|
||||
endX: number,
|
||||
endY: number
|
||||
) {
|
||||
ctx.strokeStyle = '#e6eaf2'
|
||||
ctx.lineWidth = 1
|
||||
ctx.beginPath()
|
||||
@@ -311,7 +363,7 @@ function characterAndWeaponSkinText(row: Listing) {
|
||||
{ label: '武器', key: 'weapon' },
|
||||
]
|
||||
const parts = groups
|
||||
.map((group) => {
|
||||
.map(group => {
|
||||
const names = getSkinGroup(row, group.key)
|
||||
return names.length ? `${group.label}:${names.join('、')}` : ''
|
||||
})
|
||||
@@ -421,9 +473,13 @@ function formatQuantity(value: number) {
|
||||
</el-form>
|
||||
<div class="listing-action-strip">
|
||||
<el-button @click="resetFilters">重置</el-button>
|
||||
<el-button type="primary" :icon="Search" :loading="loading" @click="queryListings">查询</el-button>
|
||||
<el-button type="primary" :icon="Search" :loading="loading" @click="queryListings"
|
||||
>查询</el-button
|
||||
>
|
||||
<el-button :disabled="!listings.length" @click="copyTableScreenshot">复制截图</el-button>
|
||||
<el-button :disabled="!listings.length" @click="downloadTableScreenshot">下载截图</el-button>
|
||||
<el-button :disabled="!listings.length" @click="downloadTableScreenshot"
|
||||
>下载截图</el-button
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -504,7 +560,9 @@ function formatQuantity(value: number) {
|
||||
</el-table>
|
||||
|
||||
<div class="table-pagination">
|
||||
<span class="pagination-summary">当前页 {{ listings.length }} 条,共 {{ totalListings }} 条</span>
|
||||
<span class="pagination-summary"
|
||||
>当前页 {{ listings.length }} 条,共 {{ totalListings }} 条</span
|
||||
>
|
||||
<div class="pagination-controls">
|
||||
<span class="pagination-size-label">每页</span>
|
||||
<el-select
|
||||
@@ -520,7 +578,9 @@ function formatQuantity(value: number) {
|
||||
</el-select>
|
||||
<span class="pagination-page">{{ currentPage }}/{{ totalPages }}页</span>
|
||||
<el-button size="small" :disabled="currentPage <= 1" @click="prevPage">上页</el-button>
|
||||
<el-button size="small" :disabled="currentPage >= totalPages" @click="nextPage">下页</el-button>
|
||||
<el-button size="small" :disabled="currentPage >= totalPages" @click="nextPage"
|
||||
>下页</el-button
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
Reference in New Issue
Block a user