261 lines
8.5 KiB
Plaintext
261 lines
8.5 KiB
Plaintext
<!-- 商家端 - 店铺编辑页面 -->
|
||
<template>
|
||
<view class="shop-edit-page">
|
||
<!-- #ifdef MP-WEIXIN -->
|
||
<view style="padding-top: var(--status-bar-height); background-color: #ffffff; display: flex; flex-direction: row; align-items: flex-end; border-bottom: 1rpx solid #eeeeee; box-sizing: border-box; height: calc(88rpx + var(--status-bar-height));">
|
||
<view style="display: flex; flex-direction: row; align-items: center; padding: 0 30rpx; height: 88rpx;" @click="uni.navigateBack()">
|
||
<text style="font-size: 44rpx; color: #333333; line-height: 1; margin-right: 6rpx;">‹</text>
|
||
<text style="font-size: 28rpx; color: #333333;">返回</text>
|
||
</view>
|
||
</view>
|
||
<!-- #endif -->
|
||
<view class="section">
|
||
<view class="section-title">店铺信息</view>
|
||
|
||
<view class="form-item">
|
||
<text class="label">店铺名称 *</text>
|
||
<input class="input" v-model="shop.shop_name" placeholder="请输入店铺名称" maxlength="50"/>
|
||
</view>
|
||
|
||
<view class="form-item">
|
||
<text class="label">店铺Logo</text>
|
||
<view class="logo-uploader" @click="chooseLogo">
|
||
<image v-if="shop.shop_logo" :src="shop.shop_logo" class="logo-preview" mode="aspectFill"/>
|
||
<view v-else class="logo-placeholder">+</view>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="form-item">
|
||
<text class="label">店铺Banner</text>
|
||
<view class="banner-uploader" @click="chooseBanner">
|
||
<image v-if="shop.shop_banner" :src="shop.shop_banner" class="banner-preview" mode="aspectFill"/>
|
||
<view v-else class="banner-placeholder">点击上传店铺Banner</view>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="form-item">
|
||
<text class="label">店铺简介</text>
|
||
<textarea class="textarea" v-model="shop.description" placeholder="请输入店铺简介" maxlength="500"/>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="section">
|
||
<view class="section-title">联系方式</view>
|
||
|
||
<view class="form-item">
|
||
<text class="label">联系人</text>
|
||
<input class="input" v-model="shop.contact_name" placeholder="请输入联系人姓名"/>
|
||
</view>
|
||
|
||
<view class="form-item">
|
||
<text class="label">联系电话</text>
|
||
<input class="input" v-model="shop.contact_phone" type="number" placeholder="请输入联系电话"/>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="submit-bar">
|
||
<view class="submit-btn" @click="saveShop">保存</view>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script lang="uts">
|
||
import supa from '@/components/supadb/aksupainstance.uts'
|
||
|
||
export default {
|
||
data() {
|
||
return {
|
||
merchantId: '',
|
||
shop: {
|
||
id: '',
|
||
shop_name: '',
|
||
shop_logo: '',
|
||
shop_banner: '',
|
||
description: '',
|
||
contact_name: '',
|
||
contact_phone: ''
|
||
}
|
||
}
|
||
},
|
||
|
||
onLoad() {
|
||
this.initMerchantId()
|
||
},
|
||
|
||
methods: {
|
||
async initMerchantId() {
|
||
try {
|
||
const session = supa.getSession()
|
||
if (session != null && session.user != null) {
|
||
this.merchantId = session.user.getString('id') || ''
|
||
}
|
||
if (!this.merchantId) {
|
||
this.merchantId = uni.getStorageSync('user_id') || ''
|
||
}
|
||
this.loadShop()
|
||
} catch (e) {
|
||
console.error('获取商户ID失败:', e)
|
||
}
|
||
},
|
||
|
||
async loadShop() {
|
||
try {
|
||
const response = await supa
|
||
.from('ml_shops')
|
||
.select('*')
|
||
.eq('merchant_id', this.merchantId)
|
||
.limit(1)
|
||
.execute()
|
||
|
||
if (response.error != null || !response.data || (response.data as any[]).length === 0) {
|
||
return
|
||
}
|
||
|
||
const rawData = (response.data as any[])[0] as UTSJSONObject
|
||
this.shop = {
|
||
id: rawData.getString('id') || '',
|
||
shop_name: rawData.getString('shop_name') || '',
|
||
shop_logo: rawData.getString('shop_logo') || '',
|
||
shop_banner: rawData.getString('shop_banner') || '',
|
||
description: rawData.getString('description') || '',
|
||
contact_name: rawData.getString('contact_name') || '',
|
||
contact_phone: rawData.getString('contact_phone') || ''
|
||
}
|
||
} catch (e) {
|
||
console.error('加载店铺失败:', e)
|
||
}
|
||
},
|
||
|
||
chooseLogo() {
|
||
uni.chooseImage({
|
||
count: 1,
|
||
success: (res) => {
|
||
this.shop.shop_logo = res.tempFilePaths[0]
|
||
}
|
||
})
|
||
},
|
||
|
||
chooseBanner() {
|
||
uni.chooseImage({
|
||
count: 1,
|
||
success: (res) => {
|
||
this.shop.shop_banner = res.tempFilePaths[0]
|
||
}
|
||
})
|
||
},
|
||
|
||
async uploadImageToSupa(localPath: string): Promise<string> {
|
||
if (localPath.startsWith('http://') || localPath.startsWith('https://')) {
|
||
return localPath
|
||
}
|
||
|
||
let ext = '.jpg'
|
||
const dotIndex = localPath.lastIndexOf('.')
|
||
if (dotIndex > -1) {
|
||
ext = localPath.substring(dotIndex).toLowerCase()
|
||
}
|
||
|
||
const uuid = Date.now().toString() + '_' + Math.floor(Math.random() * 1000)
|
||
const remotePath = `shops/${this.merchantId}_${uuid}${ext}`
|
||
|
||
try {
|
||
const uploadResult = await supa.storage.from('zhipao').upload(remotePath, localPath, {})
|
||
if (uploadResult.status == 200 || uploadResult.status == 201) {
|
||
const data = uploadResult.data
|
||
if (data != null) {
|
||
const dataObj = data as UTSJSONObject
|
||
const key = dataObj.getString('Key')
|
||
if (key != null && key != '') {
|
||
return `${supa.baseUrl}/storage/v1/object/public/${key}`
|
||
}
|
||
}
|
||
}
|
||
console.error('上传图片失败:', uploadResult.error)
|
||
return localPath
|
||
} catch (e) {
|
||
console.error('上传图片异常:', e)
|
||
return localPath
|
||
}
|
||
},
|
||
|
||
async saveShop() {
|
||
if (!this.shop.shop_name) {
|
||
uni.showToast({ title: '请输入店铺名称', icon: 'none' })
|
||
return
|
||
}
|
||
|
||
uni.showLoading({ title: '正在上传图片...' })
|
||
|
||
try {
|
||
let finalLogo = this.shop.shop_logo
|
||
if (finalLogo != '' && !finalLogo.startsWith('http')) {
|
||
finalLogo = await this.uploadImageToSupa(finalLogo)
|
||
}
|
||
|
||
let finalBanner = this.shop.shop_banner
|
||
if (finalBanner != '' && !finalBanner.startsWith('http')) {
|
||
finalBanner = await this.uploadImageToSupa(finalBanner)
|
||
}
|
||
|
||
uni.showLoading({ title: '保存中...' })
|
||
|
||
const shopData = {
|
||
shop_name: this.shop.shop_name,
|
||
shop_logo: finalLogo,
|
||
shop_banner: finalBanner,
|
||
description: this.shop.description,
|
||
contact_name: this.shop.contact_name,
|
||
contact_phone: this.shop.contact_phone,
|
||
updated_at: new Date().toISOString()
|
||
}
|
||
|
||
let response
|
||
if (this.shop.id) {
|
||
response = await supa
|
||
.from('ml_shops')
|
||
.update(shopData)
|
||
.eq('id', this.shop.id)
|
||
.execute()
|
||
} else {
|
||
shopData['merchant_id'] = this.merchantId
|
||
shopData['created_at'] = new Date().toISOString()
|
||
response = await supa
|
||
.from('ml_shops')
|
||
.insert(shopData)
|
||
.execute()
|
||
}
|
||
|
||
uni.hideLoading()
|
||
|
||
if (response.error != null) {
|
||
uni.showToast({ title: '保存失败', icon: 'none' })
|
||
return
|
||
}
|
||
|
||
uni.showToast({ title: '保存成功', icon: 'success' })
|
||
setTimeout(() => uni.navigateBack(), 1500)
|
||
} catch (e) {
|
||
uni.hideLoading()
|
||
uni.showToast({ title: '保存失败', icon: 'none' })
|
||
}
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style>
|
||
.shop-edit-page { background-color: #f5f5f5; min-height: 100vh; padding-bottom: 160rpx; }
|
||
.section { background-color: #fff; margin-bottom: 20rpx; padding: 30rpx; }
|
||
.section-title { font-size: 30rpx; font-weight: bold; color: #333; margin-bottom: 30rpx; padding-bottom: 20rpx; border-bottom: 1rpx solid #f5f5f5; }
|
||
.form-item { margin-bottom: 30rpx; }
|
||
.label { font-size: 28rpx; color: #333; display: block; margin-bottom: 16rpx; }
|
||
.input { height: 72rpx; border: 1rpx solid #e5e5e5; border-radius: 8rpx; padding: 0 20rpx; font-size: 28rpx; }
|
||
.textarea { width: 100%; height: 150rpx; border: 1rpx solid #e5e5e5; border-radius: 8rpx; padding: 20rpx; font-size: 28rpx; box-sizing: border-box; }
|
||
.logo-uploader, .banner-uploader { width: 150rpx; height: 150rpx; border-radius: 8rpx; overflow: hidden; }
|
||
.banner-uploader { width: 100%; height: 200rpx; }
|
||
.logo-preview, .banner-preview { width: 100%; height: 100%; }
|
||
.logo-placeholder, .banner-placeholder { width: 100%; height: 100%; background-color: #f5f5f5; display: flex; align-items: center; justify-content: center; font-size: 40rpx; color: #999; border: 2rpx dashed #ddd; }
|
||
.submit-bar { position: fixed; bottom: 0; left: 0; right: 0; padding: 20rpx 30rpx; padding-bottom: calc(20rpx + env(safe-area-inset-bottom)); background-color: #fff; box-shadow: 0 -2rpx 10rpx rgba(0,0,0,0.05); }
|
||
.submit-btn { height: 88rpx; line-height: 88rpx; text-align: center; font-size: 32rpx; font-weight: bold; border-radius: 44rpx; background: linear-gradient(135deg, #007AFF 0%, #5856D6 100%); color: #fff; }
|
||
</style>
|