优化商品管理筛选功能
This commit is contained in:
@@ -81,6 +81,10 @@ type AdminListQuery struct {
|
|||||||
Load []string
|
Load []string
|
||||||
SkinGroup []string
|
SkinGroup []string
|
||||||
SkinName []string
|
SkinName []string
|
||||||
|
MinCoin *float64
|
||||||
|
MaxCoin *float64
|
||||||
|
MinDeposit *float64
|
||||||
|
MaxDeposit *float64
|
||||||
Limit int
|
Limit int
|
||||||
Page int
|
Page int
|
||||||
PageSize int
|
PageSize int
|
||||||
|
|||||||
@@ -79,6 +79,10 @@ func parseAdminListQuery(c *gin.Context) (AdminListQuery, bool) {
|
|||||||
query.Load = parseCSVQuery(c.Query("load"))
|
query.Load = parseCSVQuery(c.Query("load"))
|
||||||
query.SkinGroup = parseCSVQuery(c.Query("skin_group"))
|
query.SkinGroup = parseCSVQuery(c.Query("skin_group"))
|
||||||
query.SkinName = parseCSVQuery(firstNonEmpty(c.Query("skin_name"), c.Query("skin")))
|
query.SkinName = parseCSVQuery(firstNonEmpty(c.Query("skin_name"), c.Query("skin")))
|
||||||
|
query.MinCoin = parseOptionalFloat(c.Query("min_coin"))
|
||||||
|
query.MaxCoin = parseOptionalFloat(c.Query("max_coin"))
|
||||||
|
query.MinDeposit = parseOptionalFloat(c.Query("min_deposit"))
|
||||||
|
query.MaxDeposit = parseOptionalFloat(c.Query("max_deposit"))
|
||||||
return query, true
|
return query, true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package listing
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"math"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
@@ -113,9 +114,41 @@ func (r *Repository) applyAdminListFilters(db *gorm.DB, query AdminListQuery) *g
|
|||||||
if query.ReviewStatus != "" {
|
if query.ReviewStatus != "" {
|
||||||
db = db.Where("l.review_status = ?", query.ReviewStatus)
|
db = db.Where("l.review_status = ?", query.ReviewStatus)
|
||||||
}
|
}
|
||||||
|
if query.MinCoin != nil {
|
||||||
|
db = db.Where(
|
||||||
|
"EXISTS (SELECT 1 FROM game_accounts AS coin_account WHERE coin_account.id = l.account_id AND coin_account.haf_coin_amount >= ?)",
|
||||||
|
coinMToAdminAmount(*query.MinCoin),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if query.MaxCoin != nil {
|
||||||
|
db = db.Where(
|
||||||
|
"EXISTS (SELECT 1 FROM game_accounts AS coin_account WHERE coin_account.id = l.account_id AND coin_account.haf_coin_amount <= ?)",
|
||||||
|
coinMToAdminAmount(*query.MaxCoin),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if query.MinDeposit != nil {
|
||||||
|
db = db.Where("l.deposit_amount_cent >= ?", yuanToAdminCent(*query.MinDeposit))
|
||||||
|
}
|
||||||
|
if query.MaxDeposit != nil {
|
||||||
|
db = db.Where("l.deposit_amount_cent <= ?", yuanToAdminCent(*query.MaxDeposit))
|
||||||
|
}
|
||||||
return db
|
return db
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func coinMToAdminAmount(value float64) int64 {
|
||||||
|
if value <= 0 || math.IsNaN(value) || math.IsInf(value, 0) {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return int64(math.Round(value * 1000000))
|
||||||
|
}
|
||||||
|
|
||||||
|
func yuanToAdminCent(value float64) int64 {
|
||||||
|
if value <= 0 || math.IsNaN(value) || math.IsInf(value, 0) {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return int64(math.Round(value * 100))
|
||||||
|
}
|
||||||
|
|
||||||
func (r *Repository) FindAdmin(ctx context.Context, listingID uint64) (*ListingDTO, error) {
|
func (r *Repository) FindAdmin(ctx context.Context, listingID uint64) (*ListingDTO, error) {
|
||||||
return r.findDTO(ctx, "l.id = ?", listingID)
|
return r.findDTO(ctx, "l.id = ?", listingID)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,6 +36,10 @@ const filters = reactive<AdminListingQuery>({
|
|||||||
load: '',
|
load: '',
|
||||||
skin_group: '',
|
skin_group: '',
|
||||||
skin_name: '',
|
skin_name: '',
|
||||||
|
min_coin: undefined,
|
||||||
|
max_coin: undefined,
|
||||||
|
min_deposit: undefined,
|
||||||
|
max_deposit: undefined,
|
||||||
})
|
})
|
||||||
|
|
||||||
type FilterPopover = 'asset' | 'skin'
|
type FilterPopover = 'asset' | 'skin'
|
||||||
@@ -148,6 +152,10 @@ function resetFilters() {
|
|||||||
filters.owner_id = ''
|
filters.owner_id = ''
|
||||||
filters.status = ''
|
filters.status = ''
|
||||||
filters.review_status = ''
|
filters.review_status = ''
|
||||||
|
filters.min_coin = undefined
|
||||||
|
filters.max_coin = undefined
|
||||||
|
filters.min_deposit = undefined
|
||||||
|
filters.max_deposit = undefined
|
||||||
clearAssetFilters(false)
|
clearAssetFilters(false)
|
||||||
clearSkinFilters(false)
|
clearSkinFilters(false)
|
||||||
void queryListings()
|
void queryListings()
|
||||||
@@ -551,32 +559,63 @@ function formatQuantity(value: number) {
|
|||||||
|
|
||||||
<!-- 筛选和操作行 -->
|
<!-- 筛选和操作行 -->
|
||||||
<div class="listing-filter-row">
|
<div class="listing-filter-row">
|
||||||
<el-form class="listing-filter-bar" inline>
|
<el-form class="listing-filter-bar" label-position="top">
|
||||||
<el-form-item label="编号">
|
<el-form-item class="filter-keyword" label="编号">
|
||||||
<el-input
|
<el-input
|
||||||
v-model="filters.keyword"
|
v-model="filters.keyword"
|
||||||
clearable
|
clearable
|
||||||
placeholder="商品编号 / 订单编号"
|
placeholder="商品编号 / 订单编号"
|
||||||
style="width: 210px"
|
|
||||||
@keyup.enter="queryListings"
|
@keyup.enter="queryListings"
|
||||||
@clear="queryListings"
|
@clear="queryListings"
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="号主 ID">
|
<el-form-item class="filter-owner" label="号主 ID">
|
||||||
<el-input
|
<el-input v-model="filters.owner_id" clearable placeholder="筛选号主" />
|
||||||
v-model="filters.owner_id"
|
|
||||||
clearable
|
|
||||||
placeholder="筛选号主"
|
|
||||||
style="width: 160px"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="商品状态">
|
<el-form-item class="filter-range" label="纯币(M)">
|
||||||
<el-select
|
<div class="admin-range-filter">
|
||||||
v-model="filters.status"
|
<el-input-number
|
||||||
clearable
|
v-model="filters.min_coin"
|
||||||
placeholder="全部状态"
|
:min="0"
|
||||||
style="width: 140px"
|
:precision="1"
|
||||||
>
|
:step="10"
|
||||||
|
:controls="false"
|
||||||
|
placeholder="最低"
|
||||||
|
/>
|
||||||
|
<span class="admin-range-separator">-</span>
|
||||||
|
<el-input-number
|
||||||
|
v-model="filters.max_coin"
|
||||||
|
:min="0"
|
||||||
|
:precision="1"
|
||||||
|
:step="10"
|
||||||
|
:controls="false"
|
||||||
|
placeholder="最高"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item class="filter-range" label="押金(元)">
|
||||||
|
<div class="admin-range-filter">
|
||||||
|
<el-input-number
|
||||||
|
v-model="filters.min_deposit"
|
||||||
|
:min="0"
|
||||||
|
:precision="1"
|
||||||
|
:step="100"
|
||||||
|
:controls="false"
|
||||||
|
placeholder="最低"
|
||||||
|
/>
|
||||||
|
<span class="admin-range-separator">-</span>
|
||||||
|
<el-input-number
|
||||||
|
v-model="filters.max_deposit"
|
||||||
|
:min="0"
|
||||||
|
:precision="1"
|
||||||
|
:step="100"
|
||||||
|
:controls="false"
|
||||||
|
placeholder="最高"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item class="filter-select" label="商品状态">
|
||||||
|
<el-select v-model="filters.status" clearable placeholder="全部状态">
|
||||||
<el-option label="草稿" value="draft" />
|
<el-option label="草稿" value="draft" />
|
||||||
<el-option label="已上架" value="published" />
|
<el-option label="已上架" value="published" />
|
||||||
<el-option label="已锁定" value="rented" />
|
<el-option label="已锁定" value="rented" />
|
||||||
@@ -585,20 +624,15 @@ function formatQuantity(value: number) {
|
|||||||
<el-option label="异常" value="abnormal" />
|
<el-option label="异常" value="abnormal" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="审核状态">
|
<el-form-item class="filter-select" label="审核状态">
|
||||||
<el-select
|
<el-select v-model="filters.review_status" clearable placeholder="全部审核">
|
||||||
v-model="filters.review_status"
|
|
||||||
clearable
|
|
||||||
placeholder="全部审核"
|
|
||||||
style="width: 140px"
|
|
||||||
>
|
|
||||||
<el-option label="未提交" value="none" />
|
<el-option label="未提交" value="none" />
|
||||||
<el-option label="待审核" value="pending" />
|
<el-option label="待审核" value="pending" />
|
||||||
<el-option label="已通过" value="approved" />
|
<el-option label="已通过" value="approved" />
|
||||||
<el-option label="已拒绝" value="rejected" />
|
<el-option label="已拒绝" value="rejected" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="资产">
|
<el-form-item class="filter-select" label="资产">
|
||||||
<el-popover
|
<el-popover
|
||||||
:visible="activeFilterPopover === 'asset'"
|
:visible="activeFilterPopover === 'asset'"
|
||||||
trigger="click"
|
trigger="click"
|
||||||
@@ -692,7 +726,7 @@ function formatQuantity(value: number) {
|
|||||||
</div>
|
</div>
|
||||||
</el-popover>
|
</el-popover>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="皮肤">
|
<el-form-item class="filter-skin" label="皮肤">
|
||||||
<el-popover
|
<el-popover
|
||||||
:visible="activeFilterPopover === 'skin'"
|
:visible="activeFilterPopover === 'skin'"
|
||||||
trigger="click"
|
trigger="click"
|
||||||
|
|||||||
@@ -171,6 +171,10 @@ export interface AdminListingQuery {
|
|||||||
load?: string
|
load?: string
|
||||||
skin_group?: string
|
skin_group?: string
|
||||||
skin_name?: string
|
skin_name?: string
|
||||||
|
min_coin?: number
|
||||||
|
max_coin?: number
|
||||||
|
min_deposit?: number
|
||||||
|
max_deposit?: number
|
||||||
limit?: number
|
limit?: number
|
||||||
page?: number
|
page?: number
|
||||||
page_size?: number
|
page_size?: number
|
||||||
@@ -185,7 +189,9 @@ export interface AdminListingPage {
|
|||||||
|
|
||||||
export async function fetchAdminListings(query: AdminListingQuery = {}) {
|
export async function fetchAdminListings(query: AdminListingQuery = {}) {
|
||||||
const params = Object.fromEntries(
|
const params = Object.fromEntries(
|
||||||
Object.entries(query).filter(([, value]) => value !== '' && value !== undefined)
|
Object.entries(query).filter(
|
||||||
|
([, value]) => value !== '' && value !== undefined && value !== null
|
||||||
|
)
|
||||||
)
|
)
|
||||||
const { data } = await apiClient.get<ApiResponse<AdminListingPage>>('/admin/listings', { params })
|
const { data } = await apiClient.get<ApiResponse<AdminListingPage>>('/admin/listings', { params })
|
||||||
return normalizeAdminListingPage(data.data, query)
|
return normalizeAdminListingPage(data.data, query)
|
||||||
|
|||||||
@@ -131,6 +131,7 @@ const detailScreenshots = computed(() => {
|
|||||||
url,
|
url,
|
||||||
}))
|
}))
|
||||||
})
|
})
|
||||||
|
const detailScreenshotUrls = computed(() => detailScreenshots.value.map(shot => shot.url))
|
||||||
|
|
||||||
function readGroupedScreenshots(item: Listing) {
|
function readGroupedScreenshots(item: Listing) {
|
||||||
const groups = item.asset_summary?.screenshot_groups
|
const groups = item.asset_summary?.screenshot_groups
|
||||||
@@ -462,8 +463,20 @@ function handleToggleFavorite() {
|
|||||||
<span>{{ detailScreenshots.length }} 张</span>
|
<span>{{ detailScreenshots.length }} 张</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="detail-screenshot-grid">
|
<div class="detail-screenshot-grid">
|
||||||
<figure v-for="shot in detailScreenshots" :key="shot.url" class="detail-screenshot">
|
<figure
|
||||||
<AuthImage :source="shot.url" :alt="shot.label" />
|
v-for="(shot, index) in detailScreenshots"
|
||||||
|
:key="shot.url"
|
||||||
|
class="detail-screenshot"
|
||||||
|
>
|
||||||
|
<AuthImage
|
||||||
|
:source="shot.url"
|
||||||
|
:alt="shot.label"
|
||||||
|
image-class="detail-screenshot-image"
|
||||||
|
fallback-class="detail-screenshot-image"
|
||||||
|
fit="cover"
|
||||||
|
:preview-src-list="detailScreenshotUrls"
|
||||||
|
:preview-initial-index="index"
|
||||||
|
/>
|
||||||
<figcaption>{{ shot.label }}</figcaption>
|
<figcaption>{{ shot.label }}</figcaption>
|
||||||
</figure>
|
</figure>
|
||||||
</div>
|
</div>
|
||||||
@@ -908,12 +921,20 @@ function handleToggleFavorite() {
|
|||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.detail-screenshot img {
|
.detail-screenshot-image {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
aspect-ratio: 16 / 10;
|
aspect-ratio: 16 / 10;
|
||||||
object-fit: cover;
|
overflow: hidden;
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
border: 1px solid #edf0f4;
|
border: 1px solid #edf0f4;
|
||||||
|
background: #f8fafc;
|
||||||
|
cursor: zoom-in;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-screenshot-image :deep(.el-image__inner) {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
object-fit: cover;
|
||||||
}
|
}
|
||||||
|
|
||||||
.detail-screenshot figcaption {
|
.detail-screenshot figcaption {
|
||||||
@@ -996,8 +1017,7 @@ function handleToggleFavorite() {
|
|||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
border: 1px solid rgba(245, 158, 11, 0.2);
|
border: 1px solid rgba(245, 158, 11, 0.2);
|
||||||
background:
|
background:
|
||||||
linear-gradient(135deg, rgba(255, 251, 235, 0.96), rgba(255, 247, 237, 0.92)),
|
linear-gradient(135deg, rgba(255, 251, 235, 0.96), rgba(255, 247, 237, 0.92)), #fffbeb;
|
||||||
#fffbeb;
|
|
||||||
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.86);
|
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.86);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -133,6 +133,7 @@ const detailScreenshots = computed(() => {
|
|||||||
url,
|
url,
|
||||||
}))
|
}))
|
||||||
})
|
})
|
||||||
|
const detailScreenshotUrls = computed(() => detailScreenshots.value.map(shot => shot.url))
|
||||||
|
|
||||||
function readGroupedScreenshots(item: Listing) {
|
function readGroupedScreenshots(item: Listing) {
|
||||||
const groups = item.asset_summary?.screenshot_groups
|
const groups = item.asset_summary?.screenshot_groups
|
||||||
@@ -328,7 +329,9 @@ function handleToggleFavorite() {
|
|||||||
:source="detailScreenshots[0].url"
|
:source="detailScreenshots[0].url"
|
||||||
:alt="getListingTitle(listing)"
|
:alt="getListingTitle(listing)"
|
||||||
image-class="cover-img"
|
image-class="cover-img"
|
||||||
|
fit="cover"
|
||||||
loading="eager"
|
loading="eager"
|
||||||
|
:preview-src-list="detailScreenshotUrls"
|
||||||
/>
|
/>
|
||||||
<div v-else class="cover-placeholder">
|
<div v-else class="cover-placeholder">
|
||||||
<van-icon name="photo-o" :size="40" color="#ccc" />
|
<van-icon name="photo-o" :size="40" color="#ccc" />
|
||||||
@@ -449,8 +452,20 @@ function handleToggleFavorite() {
|
|||||||
<div v-if="detailScreenshots.length" class="info-card">
|
<div v-if="detailScreenshots.length" class="info-card">
|
||||||
<h3 class="card-subtitle">账号截图</h3>
|
<h3 class="card-subtitle">账号截图</h3>
|
||||||
<div class="screenshot-grid">
|
<div class="screenshot-grid">
|
||||||
<figure v-for="shot in detailScreenshots" :key="shot.url" class="screenshot-item">
|
<figure
|
||||||
<AuthImage :source="shot.url" :alt="shot.label" image-class="screenshot-thumb" />
|
v-for="(shot, index) in detailScreenshots"
|
||||||
|
:key="shot.url"
|
||||||
|
class="screenshot-item"
|
||||||
|
>
|
||||||
|
<AuthImage
|
||||||
|
:source="shot.url"
|
||||||
|
:alt="shot.label"
|
||||||
|
image-class="screenshot-thumb"
|
||||||
|
fallback-class="screenshot-thumb"
|
||||||
|
fit="cover"
|
||||||
|
:preview-src-list="detailScreenshotUrls"
|
||||||
|
:preview-initial-index="index"
|
||||||
|
/>
|
||||||
<figcaption>{{ shot.label }}</figcaption>
|
<figcaption>{{ shot.label }}</figcaption>
|
||||||
</figure>
|
</figure>
|
||||||
</div>
|
</div>
|
||||||
@@ -630,6 +645,12 @@ function handleToggleFavorite() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.cover-img {
|
.cover-img {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
cursor: zoom-in;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cover-img :deep(.el-image__inner) {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
object-fit: cover;
|
object-fit: cover;
|
||||||
@@ -876,11 +897,18 @@ function handleToggleFavorite() {
|
|||||||
.screenshot-thumb {
|
.screenshot-thumb {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
aspect-ratio: 4 / 3;
|
aspect-ratio: 4 / 3;
|
||||||
object-fit: cover;
|
overflow: hidden;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
|
background: #f8fafc;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.screenshot-thumb :deep(.el-image__inner) {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
|
|
||||||
.screenshot-item figcaption {
|
.screenshot-item figcaption {
|
||||||
margin-top: 4px;
|
margin-top: 4px;
|
||||||
color: #6b7280;
|
color: #6b7280;
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ const props = withDefaults(
|
|||||||
decoding?: 'async' | 'sync' | 'auto'
|
decoding?: 'async' | 'sync' | 'auto'
|
||||||
previewSrcList?: string[]
|
previewSrcList?: string[]
|
||||||
previewTeleported?: boolean
|
previewTeleported?: boolean
|
||||||
|
previewInitialIndex?: number
|
||||||
fit?: 'fill' | 'contain' | 'cover' | 'none' | 'scale-down'
|
fit?: 'fill' | 'contain' | 'cover' | 'none' | 'scale-down'
|
||||||
imageStyle?: any
|
imageStyle?: any
|
||||||
}>(),
|
}>(),
|
||||||
@@ -25,6 +26,7 @@ const props = withDefaults(
|
|||||||
loading: 'lazy',
|
loading: 'lazy',
|
||||||
decoding: 'async',
|
decoding: 'async',
|
||||||
previewTeleported: true,
|
previewTeleported: true,
|
||||||
|
previewInitialIndex: 0,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -105,11 +107,14 @@ onBeforeUnmount(cleanup)
|
|||||||
<template>
|
<template>
|
||||||
<el-image
|
<el-image
|
||||||
v-if="imageURL && usePreview"
|
v-if="imageURL && usePreview"
|
||||||
|
:class="imageClass"
|
||||||
:src="imageURL"
|
:src="imageURL"
|
||||||
|
:alt="alt"
|
||||||
:fit="fit"
|
:fit="fit"
|
||||||
:style="imageStyle"
|
:style="imageStyle"
|
||||||
:preview-src-list="previewURLs"
|
:preview-src-list="previewURLs"
|
||||||
:preview-teleported="previewTeleported"
|
:preview-teleported="previewTeleported"
|
||||||
|
:initial-index="previewInitialIndex"
|
||||||
/>
|
/>
|
||||||
<img
|
<img
|
||||||
v-else-if="imageURL"
|
v-else-if="imageURL"
|
||||||
|
|||||||
@@ -523,53 +523,97 @@ h1 {
|
|||||||
|
|
||||||
/* 筛选和操作行 */
|
/* 筛选和操作行 */
|
||||||
.listing-filter-row {
|
.listing-filter-row {
|
||||||
display: flex;
|
display: grid;
|
||||||
align-items: center;
|
grid-template-columns: minmax(0, 1fr) auto;
|
||||||
justify-content: space-between;
|
align-items: end;
|
||||||
gap: 16px;
|
gap: 16px 24px;
|
||||||
padding-top: 4px;
|
padding-top: 16px;
|
||||||
border-top: 1px solid #f0f3f7;
|
border-top: 1px solid #f0f3f7;
|
||||||
}
|
}
|
||||||
|
|
||||||
.listing-filter-bar {
|
.listing-filter-bar {
|
||||||
display: flex;
|
display: grid;
|
||||||
flex-wrap: wrap;
|
grid-template-columns: minmax(220px, 1.2fr) minmax(150px, 0.78fr) minmax(220px, 1fr) minmax(
|
||||||
align-items: center;
|
220px,
|
||||||
gap: 0;
|
1fr
|
||||||
|
);
|
||||||
|
align-items: end;
|
||||||
|
gap: 12px 16px;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
row-gap: 10px;
|
min-width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.listing-filter-bar .el-form-item {
|
.listing-filter-bar .el-form-item {
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
margin-right: 20px;
|
min-width: 0;
|
||||||
}
|
|
||||||
|
|
||||||
.listing-filter-bar .el-form-item:last-child {
|
|
||||||
margin-right: 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.listing-filter-bar .el-form-item__label {
|
.listing-filter-bar .el-form-item__label {
|
||||||
|
display: block;
|
||||||
|
height: 16px;
|
||||||
|
padding: 0;
|
||||||
|
margin-bottom: 6px;
|
||||||
color: #6b7785;
|
color: #6b7785;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
margin-bottom: 6px;
|
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.listing-filter-bar .el-form-item__content {
|
||||||
|
width: 100%;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.listing-filter-bar .el-input,
|
||||||
|
.listing-filter-bar .el-select,
|
||||||
|
.listing-filter-bar .admin-filter-chip,
|
||||||
|
.listing-filter-bar .admin-range-filter {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.listing-filter-bar .el-input__wrapper,
|
||||||
|
.listing-filter-bar .el-select__wrapper {
|
||||||
|
min-height: 34px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-skin {
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-range-filter {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-range-filter .el-input-number {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-range-filter .el-input__wrapper {
|
||||||
|
padding-right: 8px;
|
||||||
|
padding-left: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-range-separator {
|
||||||
|
color: #94a3b8;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
.listing-action-strip {
|
.listing-action-strip {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
padding-bottom: 1px;
|
padding-bottom: 0;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.admin-filter-chip {
|
.admin-filter-chip {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
width: 104px;
|
height: 34px;
|
||||||
height: 32px;
|
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
gap: 6px;
|
gap: 6px;
|
||||||
@@ -588,7 +632,7 @@ h1 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.admin-filter-chip.wide {
|
.admin-filter-chip.wide {
|
||||||
width: 150px;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.admin-filter-chip span {
|
.admin-filter-chip span {
|
||||||
@@ -937,12 +981,30 @@ h1 {
|
|||||||
margin-left: 0;
|
margin-left: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (max-width: 1280px) {
|
||||||
|
.listing-filter-row {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
.listing-filter-bar {
|
||||||
|
grid-template-columns: repeat(2, minmax(180px, 1fr));
|
||||||
|
}
|
||||||
|
|
||||||
|
.listing-action-strip {
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@media (max-width: 980px) {
|
@media (max-width: 980px) {
|
||||||
.listing-control-panel {
|
.listing-control-panel {
|
||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
align-items: stretch;
|
align-items: stretch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.listing-filter-row {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
|
||||||
.listing-filter-bar {
|
.listing-filter-bar {
|
||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user