需求更改开发中

This commit is contained in:
2025-10-20 10:15:13 +08:00
parent d1b3357a8e
commit a60603acd0
30 changed files with 2863 additions and 704 deletions

View File

@@ -2,6 +2,30 @@
<div class="panel" >
<h2 class="panel-title">我的店铺</h2>
<div class="panel-body">
<!-- 店铺层级说明 -->
<el-card class="guide-card" shadow="never" style="margin-bottom: 16px;">
<div slot="header" class="guide-header">店铺层级说明</div>
<div class="guide-content">
<p class="hierarchy">层级结构店铺 商品 出售机器</p>
<ol class="guide-steps">
<li>
<b>店铺唯一</b>每个用户在平台<strong>仅能创建一个店铺</strong>创建成功后
请在本页点击 <b>钱包绑定</b>配置自己的收款地址支持不同链与币种
</li>
<li>
<b>商品</b>完成钱包绑定后即可在我的店铺页面 <b>创建商品</b>
商品可按 <b>币种</b> 进行分类管理创建的商品会在商城对买家展示
商品可理解为不同算法币种的机器集合分类
</li>
<li>
<b>出售机器</b>创建商品后请进入 <b>商品列表</b> 为该商品 <b>添加出售机器明细</b>
必须添加出售机器否则买家无法下单买家点击某个商品后会看到该商品下的机器明细并进行选购
</li>
</ol>
<div class="guide-note">提示建议先创建店铺 完成钱包绑定 创建商品 添加出售机器的顺序避免漏配导致无法收款或无法下单</div>
</div>
</el-card>
<el-card v-if="loaded && hasShop" class="shop-card" shadow="hover">
<div class="shop-row">
<div class="shop-cover">
@@ -26,26 +50,48 @@
</el-button>
<el-button size="small" type="danger" @click="handleDelete">删除店铺</el-button>
<el-button size="small" type="success" @click="handleAddProduct">新增商品</el-button>
<el-button size="small" type="success" @click="handleWalletBind">钱包绑定</el-button>
</div>
</div>
</div>
</el-card>
<!-- 店铺配置表格 -->
<!-- <el-card v-if="loaded && hasShop" class="shop-config-card" shadow="never" style="margin-top: 16px;">
<el-card v-if="loaded && hasShop" class="shop-config-card" shadow="never" style="margin-top: 16px;">
<div slot="header" class="clearfix">
<span>店铺配置</span>
<span>已绑定钱包</span>
</div>
<el-table :data="shopConfigs" border style="width: 100%">
<el-table-column prop="id" label="ID" width="80" />
<el-table-column label="商品" width="120">
<template slot-scope="scope">{{ scope.row.productId === 0 ? '所有商品' : scope.row.productId }}</template>
<el-table-column prop="chain" label="" width="140" />
<el-table-column label="支付币种" >
<template slot-scope="scope">
<div class="coin-list">
<template v-if="Array.isArray(scope.row.children) && scope.row.children.length">
<el-tooltip
v-for="(c, idx) in scope.row.children"
:key="idx"
:content="String(c && c.payCoin ? c.payCoin : '').toUpperCase()"
placement="top"
>
<img
v-if="c && c.image"
class="coin-img"
:src="c.image"
:alt="(c.payCoin || '').toUpperCase()"
/>
</el-tooltip>
</template>
<template v-else>
{{ String(scope.row.payCoin || '').toUpperCase() }}
</template>
</div>
</template>
</el-table-column>
<el-table-column prop="payType" label="币种类型" width="120">
<!-- <el-table-column prop="payType" label="币种类型" width="120">
<template slot-scope="scope">{{ scope.row.payType === 1 ? '稳定币' : '虚拟币' }}</template>
</el-table-column>
<el-table-column prop="payCoin" label="支付币种" width="140" />
<el-table-column prop="payAddress" label="收款钱包地址" />
</el-table-column> -->
<el-table-column prop="payAddress" label="收款钱包地址" show-overflow-tooltip />
<el-table-column label="操作" width="180" fixed="right">
<template slot-scope="scope">
<el-button type="text" @click="handleEditConfig(scope.row)">修改</el-button>
@@ -54,7 +100,7 @@
</template>
</el-table-column>
</el-table>
</el-card> -->
</el-card>
<div v-else-if="loaded && !hasShop" class="no-shop">
<el-empty description="暂无店铺">
@@ -84,18 +130,35 @@
<el-button type="primary" @click="submitEdit">保存</el-button>
</span>
</el-dialog>
<!-- 修改店铺配置弹窗 -->
<!-- 修改钱包绑定配置弹窗参数保持与列表一致 -->
<el-dialog title="修改配置" :visible.sync="visibleConfigEdit" width="560px">
<div class="row">
<label class="label">适用商品</label>
<el-select v-model="configForm.productId" placeholder="请选择商品">
<el-option :value="0" label="所有商品" />
<el-option v-for="p in productOptions" :key="p.id" :value="p.id" :label="`${p.id} - ${p.name}`" />
<label class="label">支付链</label>
<el-select v-model="configForm.chain" placeholder="请选择">
<el-option v-for="c in chainOptions" :key="c.value" :value="c.value" :label="c.label" />
</el-select>
</div>
<div class="row">
<label class="label">收款地址</label>
<el-input v-model="configForm.payAddress" placeholder="请输入钱包地址" />
<label class="label">支付币种</label>
<el-select
class="input"
size="middle"
ref="screen"
v-model="configForm.payCoin"
placeholder="请选择币种"
>
<el-option
v-for="item in editCoinOptions"
:key="item.value"
:label="item.label"
:value="item.value"
>
<div style="display: flex; align-items: center">
<img v-if="item.imgUrl" :src="item.imgUrl" style="float: left; width: 20px" />
<span style="float: left; margin-left: 5px">{{ item.label }}</span>
</div>
</el-option>
</el-select>
</div>
<div class="row">
<label class="label">币种类型</label>
@@ -105,29 +168,8 @@
</el-radio-group>
</div>
<div class="row">
<label class="label">支付币种</label>
<el-select
class="input"
size="middle"
ref="screen"
v-model="configForm.payCoin"
placeholder="请选择"
>
<el-option
v-for="item in coinOptions"
:key="item.value"
:label="item.label"
:value="item.value"
>
<div style="display: flex; align-items: center">
<img :src="item.imgUrl" style="float: left; width: 20px" />
<span style="float: left; margin-left: 5px">
{{ item.label }}</span
>
</div>
</el-option>
</el-select>
<label class="label">钱包地址</label>
<el-input v-model="configForm.payAddress" placeholder="请输入钱包地址" />
</div>
<span slot="footer" class="dialog-footer">
<el-button @click="visibleConfigEdit=false">取消</el-button>
@@ -139,9 +181,10 @@
</template>
<script>
import { getMyShop, updateShop, deleteShop, queryShop, closeShop, getShopConfig ,updateShopConfig,deleteShopConfig} from '@/api/shops'
import { getMyShop, updateShop, deleteShop, queryShop, closeShop ,updateShopConfig,deleteShopConfig} from '@/api/shops'
import { coinList } from '@/utils/coinList'
import { getShopConfig } from '@/api/wallet'
export default {
@@ -163,9 +206,16 @@ export default {
// 店铺配置列表
shopConfigs: [],
visibleConfigEdit: false,
configForm: { id: '', payAddress: '', payCoin: '', payType: 0, productId: 0 },
configForm: { id: '', chain: '', payAddress: '', payCoin: '', payType: 0 },
productOptions: [],
coinOptions: coinList || [],
// 支付链选项(可与后端接口对齐后替换为动态)
chainOptions: [
{ label: 'Tron (TRC20)', value: 'tron' },
{ label: 'Ethereum (ERC20)', value: 'ethereum' },
{ label: 'BSC (BEP20)', value: 'bsc' },
{ label: 'Nexa', value: 'nexa' },
],
shopLoading: false
}
},
@@ -189,6 +239,19 @@ export default {
},
canCreateShop() {
return !this.hasShop
},
/**
* 弹窗可选币种:稳定币/虚拟币分流
*/
editCoinOptions() {
if (Number(this.configForm.payType) === 1) {
return [
{ label: 'USDT', value: 'usdt' },
{ label: 'USDC', value: 'usdc' },
{ label: 'BUSD', value: 'busd' },
]
}
return this.coinOptions
}
},
created() {
@@ -230,7 +293,7 @@ export default {
del: !!res.data.del,
state: Number(res.data.state || 0)
}
// 同步加载店铺配置
// 同步加载钱包绑定
this.fetchShopConfigs(res.data.id)
} else {
// 当接口返回错误或没有数据时,重置店铺状态
@@ -257,8 +320,9 @@ export default {
}
try {
const res = await getShopConfig(shopId)
const res = await getShopConfig({id:shopId})
if (res && (res.code === 0 || res.code === 200) && Array.isArray(res.data)) {
// 直接使用后端返回的数据children: [{payCoin,image}]
this.shopConfigs = res.data
} else {
this.shopConfigs = []
@@ -286,7 +350,13 @@ export default {
}
},
handleEditConfig(row) {
this.configForm = { ...row }
this.configForm = {
id: row.id,
chain: row.chain || '',
payCoin: row.payCoin || '',
payType: typeof row.payType === 'number' ? row.payType : Number(row.payType || 0),
payAddress: row.payAddress || '',
}
this.visibleConfigEdit = true
},
@@ -295,8 +365,23 @@ export default {
},
submitConfigEdit() {
this.updateShopConfig(this.configForm)
// 基础校验
if (!this.configForm.chain) {
this.$message.warning('请选择支付链')
return
}
if (!this.configForm.payCoin) {
this.$message.warning('请选择支付币种')
return
}
const addr = (this.configForm.payAddress || '').trim()
if (!addr) {
this.$message.warning('请输入钱包地址')
return
}
const { productId, ...rest } = this.configForm
const payload = { ...rest, payType: Number(this.configForm.payType || 0) }
this.updateShopConfig(payload)
},
async handleOpenEdit() {
try {
@@ -470,7 +555,26 @@ export default {
path: '/account/product-new',
query: { shopId: this.shop.id }
})
},
/**
* 跳转到钱包绑定页面
*/
handleWalletBind() {
if (!this.hasShop) {
this.$message({
message: '请先创建店铺',
type: 'warning',
showClose: true
})
return
}
this.$router.push('/account/shop-config')
}
}
}
</script>
@@ -485,6 +589,16 @@ export default {
.desc { color: #666; }
.meta { color: #999; display: flex; gap: 16px; font-size: 12px; }
.actions { margin-top: 8px; display: flex; gap: 8px; }
.guide-card { border: 1px solid #eef2f7; border-radius: 10px; }
.guide-header { text-align: center; font-weight: 700; color: #2c3e50; background: #f9fafb; border-bottom: 1px solid #eef2f7; padding: 10px 12px; border-radius: 10px 10px 0 0; }
.guide-content { padding: 4px 6px; text-align: left; }
.guide-card .hierarchy { margin: 0 0 8px 0; color: #111827; font-weight: 700; font-size: 14px; }
.guide-steps { margin: 0; padding-left: 18px; color: #374151; }
.guide-steps li { line-height: 1.9; margin: 6px 0; }
.guide-steps b { color: #111827; }
.guide-note { margin-top: 10px; color: #6b7280; font-size: 13px; background: #f9fafb; border: 1px dashed #e5e7eb; padding: 8px 10px; border-radius: 8px; }
.coin-list { display: flex; align-items: center; gap: 8px; }
.coin-img { width: 20px; height: 20px; border-radius: 4px; display: inline-block; }
</style>
<style>