Files
medical-mall/pages/mall/merchant/shop-edit.uvue

261 lines
8.5 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!-- 商家端 - 店铺编辑页面 -->
<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>