分类 preoder 和 order
This commit is contained in:
parent
efb3f2c727
commit
35928a6144
|
|
@ -28,9 +28,11 @@ import { RelatedProductsField as RelatedProductsField_f3e26ca26ab1ef52a2ee0f6932
|
|||
import { TaobaoLinkPreview as TaobaoLinkPreview_44c9439e828c0463191af62d21ad4959 } from '../../../components/fields/TaobaoLinkPreview'
|
||||
import { UnifiedSyncButton as UnifiedSyncButton_fc99b3f144909da232f9fd4ff7269523 } from '../../../components/sync/UnifiedSyncButton'
|
||||
import { default as default_c2e3814fe427263135b1f5931c37f6f2 } from '../../../components/list/ProductGridStyler'
|
||||
import { PreorderProgressCell as PreorderProgressCell_67df47753573233f0c83480de687f13b } from '../../../components/cells/PreorderProgressCell'
|
||||
import { RefreshOrderCountField as RefreshOrderCountField_ef327f0ad449eac595b5e301044c0996 } from '../../../components/fields/RefreshOrderCountField'
|
||||
import { BlocksFeatureClient as BlocksFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client'
|
||||
import { PreorderOrdersField as PreorderOrdersField_a4aa1b8cbd6dec364a834b059228f43f } from '../../../components/fields/PreorderOrdersField'
|
||||
import { RefreshOrderCountButton as RefreshOrderCountButton_f6ce1bfc16a20083ee4c6ceb7022839e } from '../../../components/sync/RefreshOrderCountButton'
|
||||
import { PreorderProductGridStyler as PreorderProductGridStyler_e7f6f7c2233fc58ae87e992227bb80c5 } from '../../../components/list/PreorderProductGridStyler'
|
||||
import { default as default_767734c8b7b095ea28d54c32abcf46e4 } from '../../../components/views/AdminPanel'
|
||||
import { default as default_a766ef013722c08f9bb937940272cb5f } from '../../../components/views/LogsManagerView'
|
||||
import { S3ClientUploadHandler as S3ClientUploadHandler_f97aa6c64367fa259c5bc0567239ef24 } from '@payloadcms/storage-s3/client'
|
||||
|
|
@ -67,9 +69,11 @@ export const importMap = {
|
|||
"/components/fields/TaobaoLinkPreview#TaobaoLinkPreview": TaobaoLinkPreview_44c9439e828c0463191af62d21ad4959,
|
||||
"/components/sync/UnifiedSyncButton#UnifiedSyncButton": UnifiedSyncButton_fc99b3f144909da232f9fd4ff7269523,
|
||||
"/components/list/ProductGridStyler#default": default_c2e3814fe427263135b1f5931c37f6f2,
|
||||
"/components/cells/PreorderProgressCell#PreorderProgressCell": PreorderProgressCell_67df47753573233f0c83480de687f13b,
|
||||
"/components/fields/RefreshOrderCountField#RefreshOrderCountField": RefreshOrderCountField_ef327f0ad449eac595b5e301044c0996,
|
||||
"@payloadcms/richtext-lexical/client#BlocksFeatureClient": BlocksFeatureClient_e70f5e05f09f93e00b997edb1ef0c864,
|
||||
"/components/fields/PreorderOrdersField#PreorderOrdersField": PreorderOrdersField_a4aa1b8cbd6dec364a834b059228f43f,
|
||||
"/components/sync/RefreshOrderCountButton#RefreshOrderCountButton": RefreshOrderCountButton_f6ce1bfc16a20083ee4c6ceb7022839e,
|
||||
"/components/list/PreorderProductGridStyler#PreorderProductGridStyler": PreorderProductGridStyler_e7f6f7c2233fc58ae87e992227bb80c5,
|
||||
"/components/views/AdminPanel#default": default_767734c8b7b095ea28d54c32abcf46e4,
|
||||
"/components/views/LogsManagerView#default": default_a766ef013722c08f9bb937940272cb5f,
|
||||
"@payloadcms/storage-s3/client#S3ClientUploadHandler": S3ClientUploadHandler_f97aa6c64367fa259c5bc0567239ef24,
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ export const PreorderProducts: CollectionConfig = {
|
|||
slug: 'preorder-products',
|
||||
admin: {
|
||||
useAsTitle: 'title',
|
||||
defaultColumns: ['thumbnail', 'title', 'medusaId', 'status', 'updatedAt'],
|
||||
defaultColumns: ['thumbnail', 'title', 'medusaId', 'progress', 'status', 'updatedAt'],
|
||||
description: '管理预售商品的详细内容和描述',
|
||||
listSearchableFields: ['title', 'medusaId'],
|
||||
pagination: {
|
||||
|
|
@ -36,13 +36,15 @@ export const PreorderProducts: CollectionConfig = {
|
|||
components: {
|
||||
beforeListTable: [
|
||||
'/components/sync/UnifiedSyncButton#UnifiedSyncButton',
|
||||
'/components/sync/RefreshOrderCountButton#RefreshOrderCountButton',
|
||||
'/components/list/ProductGridStyler',
|
||||
'/components/list/PreorderProductGridStyler#PreorderProductGridStyler',
|
||||
],
|
||||
},
|
||||
},
|
||||
access: {
|
||||
read: () => true,
|
||||
read: () => true, // 公开可读
|
||||
create: ({ req: { user } }) => !!user, // 登录用户可创建
|
||||
update: ({ req: { user } }) => !!user, // 登录用户可更新
|
||||
delete: ({ req: { user } }) => !!user, // 登录用户可删除
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
|
|
@ -123,6 +125,15 @@ export const PreorderProducts: CollectionConfig = {
|
|||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'progress',
|
||||
type: 'ui',
|
||||
admin: {
|
||||
components: {
|
||||
Cell: '/components/cells/PreorderProgressCell#PreorderProgressCell',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
|
|
@ -168,6 +179,15 @@ export const PreorderProducts: CollectionConfig = {
|
|||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'ui',
|
||||
name: 'refreshOrderCount',
|
||||
admin: {
|
||||
components: {
|
||||
Field: '/components/fields/RefreshOrderCountField#RefreshOrderCountField',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'row',
|
||||
fields: [
|
||||
|
|
@ -268,6 +288,17 @@ export const PreorderProducts: CollectionConfig = {
|
|||
Field: '/components/fields/RelatedProductsField#RelatedProductsField',
|
||||
},
|
||||
},
|
||||
filterOptions: ({ relationTo, data }) => {
|
||||
// 过滤掉当前商品本身,避免自引用
|
||||
if (data?.id) {
|
||||
return {
|
||||
id: {
|
||||
not_equals: data.id,
|
||||
},
|
||||
}
|
||||
}
|
||||
return true
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
|
|
|
|||
|
|
@ -196,6 +196,17 @@ export const Products: CollectionConfig = {
|
|||
Field: '/components/fields/RelatedProductsField#RelatedProductsField',
|
||||
},
|
||||
},
|
||||
filterOptions: ({ relationTo, data }) => {
|
||||
// 过滤掉当前商品本身,避免自引用
|
||||
if (data?.id) {
|
||||
return {
|
||||
id: {
|
||||
not_equals: data.id,
|
||||
},
|
||||
}
|
||||
}
|
||||
return true
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
|
|
|
|||
|
|
@ -0,0 +1,48 @@
|
|||
'use client'
|
||||
import React from 'react'
|
||||
|
||||
/**
|
||||
* 预购进度单元格组件
|
||||
* 在列表网格视图中显示订单计数和进度
|
||||
*/
|
||||
export function PreorderProgressCell({ rowData }: any) {
|
||||
const orderCount = parseInt(rowData?.orderCount || '0', 10) || 0
|
||||
const fakeOrderCount = parseInt(rowData?.fakeOrderCount || '0', 10) || 0
|
||||
const fundingGoal = parseInt(rowData?.fundingGoal || '0', 10) || 100
|
||||
|
||||
const totalCount = orderCount + fakeOrderCount
|
||||
const percentage = fundingGoal > 0 ? Math.min(Math.round((totalCount / fundingGoal) * 100), 100) : 0
|
||||
|
||||
return (
|
||||
<div className="preorder-progress-info">
|
||||
<div className="progress-label">
|
||||
<span>预购进度</span>
|
||||
<span className="progress-count">
|
||||
{totalCount} / {fundingGoal}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div className="progress-bar">
|
||||
<div
|
||||
className="progress-fill"
|
||||
style={{ width: `${percentage}%` }}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="progress-stats">
|
||||
<div className="stat-item">
|
||||
<span className="stat-label">真实</span>
|
||||
<span className="stat-value">{orderCount}</span>
|
||||
</div>
|
||||
<div className="stat-item">
|
||||
<span className="stat-label">Fake</span>
|
||||
<span className="stat-value">{fakeOrderCount}</span>
|
||||
</div>
|
||||
<div className="stat-item">
|
||||
<span className="stat-label">完成度</span>
|
||||
<span className="stat-value">{percentage}%</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
@ -1,19 +1,21 @@
|
|||
'use client'
|
||||
import Link from 'next/link'
|
||||
import { usePathname } from 'next/navigation'
|
||||
|
||||
export const ThumbnailCell = (props: any) => {
|
||||
console.log('=== ThumbnailCell All Props ===', props)
|
||||
console.log('Props keys:', Object.keys(props))
|
||||
const pathname = usePathname()
|
||||
|
||||
// 从 URL 路径中提取 collection slug
|
||||
const collectionSlug = pathname?.includes('/preorder-products')
|
||||
? 'preorder-products'
|
||||
: 'products'
|
||||
|
||||
// 尝试从不同的 props 路径获取值
|
||||
const value = props.value || props.cellData || props.data
|
||||
const rowData = props.rowData || props.row
|
||||
|
||||
console.log('Extracted value:', value)
|
||||
console.log('Extracted rowData:', rowData)
|
||||
|
||||
const isImage = typeof value === 'string' && value.match(/^https?:\/\/.+/)
|
||||
const editUrl = `/admin/collections/products/${rowData?.id || ''}`
|
||||
const editUrl = `/admin/collections/${collectionSlug}/${rowData?.id || ''}`
|
||||
|
||||
return (
|
||||
<Link
|
||||
|
|
|
|||
|
|
@ -0,0 +1,130 @@
|
|||
'use client'
|
||||
import { useState } from 'react'
|
||||
import { Button, useDocumentInfo } from '@payloadcms/ui'
|
||||
import { useRouter } from 'next/navigation'
|
||||
|
||||
/**
|
||||
* 编辑页面内的订单计数刷新组件
|
||||
* 只针对当前编辑的预购商品刷新订单数据
|
||||
*/
|
||||
export function RefreshOrderCountField() {
|
||||
const { id } = useDocumentInfo()
|
||||
const [loading, setLoading] = useState(false)
|
||||
const [message, setMessage] = useState('')
|
||||
const router = useRouter()
|
||||
|
||||
const handleRefresh = async () => {
|
||||
if (!id) {
|
||||
setMessage('⚠️ 无法获取商品 ID')
|
||||
return
|
||||
}
|
||||
|
||||
setLoading(true)
|
||||
setMessage('')
|
||||
|
||||
try {
|
||||
const response = await fetch('/api/refresh-order-counts', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
productIds: [id],
|
||||
}),
|
||||
})
|
||||
|
||||
const data = await response.json()
|
||||
|
||||
if (data.success) {
|
||||
setMessage(`✅ ${data.message || '订单计数刷新成功!'}`)
|
||||
// 刷新页面数据
|
||||
setTimeout(() => {
|
||||
router.refresh()
|
||||
// 重新加载页面以更新显示
|
||||
window.location.reload()
|
||||
}, 1000)
|
||||
} else {
|
||||
setMessage(`❌ 刷新失败: ${data.error || '未知错误'}`)
|
||||
}
|
||||
} catch (error) {
|
||||
setMessage('❌ 刷新出错: ' + (error instanceof Error ? error.message : '未知错误'))
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
padding: '1rem',
|
||||
border: '1px solid var(--theme-elevation-150)',
|
||||
borderRadius: '4px',
|
||||
backgroundColor: 'var(--theme-elevation-50)',
|
||||
marginBottom: '1rem',
|
||||
}}
|
||||
>
|
||||
<div style={{ marginBottom: '0.75rem' }}>
|
||||
<h4 style={{ margin: '0 0 0.5rem 0', fontSize: '0.875rem', fontWeight: 600 }}>
|
||||
📊 订单计数同步
|
||||
</h4>
|
||||
<p style={{ margin: 0, fontSize: '0.8125rem', color: 'var(--theme-elevation-600)' }}>
|
||||
从 Medusa 订单系统同步真实订单计数数据
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<Button
|
||||
onClick={handleRefresh}
|
||||
disabled={loading}
|
||||
buttonStyle="primary"
|
||||
size="small"
|
||||
>
|
||||
{loading ? '同步中...' : '🔄 刷新订单计数'}
|
||||
</Button>
|
||||
|
||||
{message && (
|
||||
<div
|
||||
style={{
|
||||
padding: '0.75rem',
|
||||
marginTop: '0.75rem',
|
||||
borderRadius: '4px',
|
||||
backgroundColor: message.startsWith('✅')
|
||||
? 'var(--theme-success-50)'
|
||||
: message.startsWith('⚠️')
|
||||
? 'var(--theme-warning-50)'
|
||||
: 'var(--theme-error-50)',
|
||||
color: message.startsWith('✅')
|
||||
? 'var(--theme-success-900)'
|
||||
: message.startsWith('⚠️')
|
||||
? 'var(--theme-warning-900)'
|
||||
: 'var(--theme-error-900)',
|
||||
fontSize: '0.8125rem',
|
||||
}}
|
||||
>
|
||||
{message}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div
|
||||
style={{
|
||||
marginTop: '0.75rem',
|
||||
padding: '0.75rem',
|
||||
backgroundColor: 'var(--theme-elevation-100)',
|
||||
borderRadius: '4px',
|
||||
fontSize: '0.8125rem',
|
||||
color: 'var(--theme-elevation-600)',
|
||||
}}
|
||||
>
|
||||
<p style={{ margin: '0.25rem 0', fontWeight: 600 }}>💡 说明:</p>
|
||||
<p style={{ margin: '0.25rem 0' }}>
|
||||
• <strong>真实订单计数</strong>:从 Medusa 自动同步,只读
|
||||
</p>
|
||||
<p style={{ margin: '0.25rem 0' }}>
|
||||
• <strong>Fake计数</strong>:上方可手动编辑
|
||||
</p>
|
||||
<p style={{ margin: '0.25rem 0' }}>
|
||||
• <strong>显示进度</strong> = 真实订单 + Fake计数
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
'use client'
|
||||
import { useEffect } from 'react'
|
||||
import './preorder-product-grid-styler.scss'
|
||||
|
||||
/**
|
||||
* 预购商品网格样式组件
|
||||
* 将列表转换为卡片网格,显示预购进度
|
||||
*/
|
||||
export function PreorderProductGridStyler() {
|
||||
useEffect(() => {
|
||||
// 组件加载时添加样式类
|
||||
const table = document.querySelector('.collection-list--preorder-products')
|
||||
if (table) {
|
||||
table.classList.add('preorder-grid-view')
|
||||
}
|
||||
|
||||
return () => {
|
||||
const table = document.querySelector('.collection-list--preorder-products')
|
||||
if (table) {
|
||||
table.classList.remove('preorder-grid-view')
|
||||
}
|
||||
}
|
||||
}, [])
|
||||
|
||||
return null // 这是一个纯样式组件,不渲染任何内容
|
||||
}
|
||||
|
|
@ -0,0 +1,240 @@
|
|||
// 预购商品网格视图样式
|
||||
// 将表格转换为卡片网格,显示预购进度
|
||||
|
||||
.collection-list.collection-list--preorder-products.preorder-grid-view {
|
||||
// 隐藏表头
|
||||
thead {
|
||||
display: none;
|
||||
}
|
||||
|
||||
// 主体使用 Grid 布局
|
||||
tbody {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
|
||||
gap: 1.5rem;
|
||||
padding: 1rem 0;
|
||||
}
|
||||
|
||||
// 每个 tr 变成卡片
|
||||
tr {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
border: 1px solid var(--theme-elevation-150);
|
||||
border-radius: 8px;
|
||||
padding: 1rem;
|
||||
background: var(--theme-elevation-0);
|
||||
transition: all 0.2s ease;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
|
||||
&:hover {
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
||||
border-color: var(--theme-elevation-300);
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
// 选中状态
|
||||
&.row-selected {
|
||||
border-color: var(--theme-success-500);
|
||||
background: var(--theme-success-50);
|
||||
}
|
||||
}
|
||||
|
||||
// 所有单元格
|
||||
td {
|
||||
border: none !important;
|
||||
padding: 0.25rem 0 !important;
|
||||
background: transparent !important;
|
||||
width: 100% !important;
|
||||
max-width: none !important;
|
||||
|
||||
// 隐藏不需要的列
|
||||
&:not([class*='thumbnail']):not([class*='title']):not([class*='medusaId']):not([class*='status']):not([class*='updatedAt']) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
// 缩略图
|
||||
td[class*='thumbnail'] {
|
||||
order: -1;
|
||||
margin-bottom: 0.75rem;
|
||||
|
||||
img {
|
||||
width: 100%;
|
||||
height: 200px;
|
||||
object-fit: cover;
|
||||
border-radius: 6px;
|
||||
background: var(--theme-elevation-100);
|
||||
}
|
||||
|
||||
// 如果没有图片,显示占位符
|
||||
&:empty::before {
|
||||
content: '📦';
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
height: 200px;
|
||||
font-size: 4rem;
|
||||
background: var(--theme-elevation-100);
|
||||
border-radius: 6px;
|
||||
color: var(--theme-elevation-400);
|
||||
}
|
||||
}
|
||||
|
||||
// 标题
|
||||
td[class*='title'] {
|
||||
font-size: 1rem;
|
||||
font-weight: 600;
|
||||
color: var(--theme-elevation-1000);
|
||||
margin-bottom: 0.5rem;
|
||||
line-height: 1.4;
|
||||
|
||||
// 限制两行,超出省略
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 2;
|
||||
line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
// Medusa ID
|
||||
td[class*='medusaId'] {
|
||||
font-size: 0.75rem;
|
||||
color: var(--theme-elevation-500);
|
||||
font-family: monospace;
|
||||
margin-bottom: 0.5rem;
|
||||
|
||||
&::before {
|
||||
content: '🆔 ';
|
||||
}
|
||||
}
|
||||
|
||||
// 状态标签
|
||||
td[class*='status'] {
|
||||
margin: 0.5rem 0;
|
||||
|
||||
.pill {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
padding: 0.25rem 0.75rem;
|
||||
border-radius: 12px;
|
||||
font-size: 0.75rem;
|
||||
font-weight: 500;
|
||||
|
||||
&.pill--published {
|
||||
background: var(--theme-success-100);
|
||||
color: var(--theme-success-900);
|
||||
}
|
||||
|
||||
&.pill--draft {
|
||||
background: var(--theme-warning-100);
|
||||
color: var(--theme-warning-900);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 更新时间
|
||||
td[class*='updatedAt'] {
|
||||
font-size: 0.75rem;
|
||||
color: var(--theme-elevation-500);
|
||||
margin-top: auto;
|
||||
padding-top: 0.75rem !important;
|
||||
border-top: 1px solid var(--theme-elevation-100);
|
||||
|
||||
&::before {
|
||||
content: '🕐 ';
|
||||
}
|
||||
}
|
||||
|
||||
// 复选框单元格
|
||||
td:first-child {
|
||||
position: absolute;
|
||||
top: 0.75rem;
|
||||
right: 0.75rem;
|
||||
width: auto !important;
|
||||
z-index: 10;
|
||||
|
||||
input[type='checkbox'] {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
cursor: pointer;
|
||||
border: 2px solid var(--theme-elevation-400);
|
||||
border-radius: 4px;
|
||||
|
||||
&:checked {
|
||||
background: var(--theme-success-500);
|
||||
border-color: var(--theme-success-500);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 操作按钮单元格
|
||||
td:last-child {
|
||||
position: absolute;
|
||||
bottom: 0.75rem;
|
||||
right: 0.75rem;
|
||||
width: auto !important;
|
||||
}
|
||||
}
|
||||
|
||||
// 预购进度信息(需要通过自定义 Cell 组件添加)
|
||||
.preorder-progress-info {
|
||||
margin: 0.75rem 0;
|
||||
padding: 0.75rem;
|
||||
background: var(--theme-elevation-50);
|
||||
border-radius: 6px;
|
||||
border: 1px solid var(--theme-elevation-150);
|
||||
|
||||
.progress-label {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
font-size: 0.75rem;
|
||||
color: var(--theme-elevation-600);
|
||||
margin-bottom: 0.5rem;
|
||||
|
||||
.progress-count {
|
||||
font-weight: 600;
|
||||
color: var(--theme-elevation-900);
|
||||
}
|
||||
}
|
||||
|
||||
.progress-bar {
|
||||
width: 100%;
|
||||
height: 8px;
|
||||
background: var(--theme-elevation-150);
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
|
||||
.progress-fill {
|
||||
height: 100%;
|
||||
background: linear-gradient(90deg, var(--theme-success-500), var(--theme-success-600));
|
||||
transition: width 0.3s ease;
|
||||
border-radius: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
.progress-stats {
|
||||
display: flex;
|
||||
gap: 1rem;
|
||||
margin-top: 0.5rem;
|
||||
font-size: 0.75rem;
|
||||
|
||||
.stat-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.stat-label {
|
||||
color: var(--theme-elevation-500);
|
||||
margin-bottom: 0.125rem;
|
||||
}
|
||||
|
||||
.stat-value {
|
||||
font-weight: 600;
|
||||
color: var(--theme-elevation-900);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue