feat: 商家端代码

This commit is contained in:
FlowerWater
2025-12-19 12:04:22 +08:00
parent 3c21b074c4
commit 9591234e70
22 changed files with 4776 additions and 210 deletions

View File

@@ -0,0 +1,246 @@
<script lang="ts" setup>
import { useMerchantStore } from '@/store/merchant'
import { updateShopInfo as apiUpdateShopInfo } from '@/pagesMerchant/api'
definePage({
style: {
navigationBarTitleText: '店铺设置',
},
})
const merchantStore = useMerchantStore()
// 表单数据
const formData = ref({
name: '',
phone: '',
address: '',
businessHours: '',
description: '',
})
// 加载店铺信息
async function loadShopInfo() {
await merchantStore.fetchShopInfo()
if (merchantStore.shopInfo) {
formData.value = {
name: merchantStore.shopInfo.name,
phone: merchantStore.shopInfo.phone,
address: merchantStore.shopInfo.address,
businessHours: merchantStore.shopInfo.businessHours,
description: merchantStore.shopInfo.description || '',
}
}
}
// 选择头像
function handleChooseAvatar() {
uni.chooseImage({
count: 1,
success: (res) => {
// 实际项目中这里需要上传图片
uni.showToast({ title: '头像已选择', icon: 'success' })
},
})
}
// 保存
async function handleSave() {
if (!formData.value.name.trim()) {
uni.showToast({ title: '请输入店铺名称', icon: 'none' })
return
}
uni.showLoading({ title: '保存中...' })
try {
await apiUpdateShopInfo(formData.value)
uni.hideLoading()
uni.showToast({ title: '保存成功', icon: 'success' })
} catch (error) {
uni.hideLoading()
uni.showToast({ title: '保存失败', icon: 'none' })
}
}
onMounted(() => {
loadShopInfo()
})
</script>
<template>
<view class="shop-page">
<view class="form-wrapper">
<!-- 店铺头像 -->
<view class="avatar-section" @click="handleChooseAvatar">
<text class="label">店铺头像</text>
<view class="avatar">
<image :src="merchantStore.shopInfo?.logo || '/static/images/shop-logo.jpg'" mode="aspectFill" />
<text class="i-carbon-camera"></text>
</view>
</view>
<!-- 表单 -->
<view class="form-section">
<view class="form-item">
<text class="label">店铺名称</text>
<input v-model="formData.name" placeholder="请输入店铺名称" class="input" />
</view>
<view class="form-item">
<text class="label">联系电话</text>
<input v-model="formData.phone" type="tel" placeholder="请输入联系电话" class="input" />
</view>
<view class="form-item">
<text class="label">店铺地址</text>
<input v-model="formData.address" placeholder="请输入店铺地址" class="input" />
</view>
<view class="form-item">
<text class="label">营业时间</text>
<input v-model="formData.businessHours" placeholder="如09:00 - 22:00" class="input" />
</view>
<view class="form-item textarea-item">
<text class="label">店铺简介</text>
<textarea v-model="formData.description" placeholder="请输入店铺简介" class="textarea" />
</view>
</view>
</view>
<!-- 保存按钮 -->
<view class="footer-bar">
<view class="save-btn" @click="handleSave">保存</view>
</view>
</view>
</template>
<style lang="scss" scoped>
.shop-page {
min-height: 100vh;
background: #f5f5f5;
padding-bottom: 140rpx;
width: 100%;
max-width: 540px;
margin: 0 auto;
}
.form-wrapper {
padding: 20rpx;
}
.avatar-section {
background: #fff;
border-radius: 16rpx;
padding: 24rpx;
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20rpx;
.label {
font-size: 28rpx;
color: #333;
}
.avatar {
position: relative;
width: 120rpx;
height: 120rpx;
border-radius: 16rpx;
overflow: hidden;
image {
width: 100%;
height: 100%;
}
text {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
width: 56rpx;
height: 56rpx;
border-radius: 50%;
background: rgba(0, 0, 0, 0.5);
display: flex;
align-items: center;
justify-content: center;
font-size: 32rpx;
color: #fff;
}
}
}
.form-section {
background: #fff;
border-radius: 16rpx;
padding: 0 24rpx;
.form-item {
display: flex;
align-items: center;
padding: 28rpx 0;
border-bottom: 1rpx solid #f5f5f5;
&:last-child {
border-bottom: none;
}
.label {
width: 160rpx;
font-size: 28rpx;
color: #333;
flex-shrink: 0;
}
.input {
flex: 1;
font-size: 28rpx;
text-align: right;
}
&.textarea-item {
flex-direction: column;
align-items: flex-start;
.label {
margin-bottom: 16rpx;
}
.textarea {
width: 100%;
height: 160rpx;
background: #f5f5f5;
border-radius: 12rpx;
padding: 20rpx;
font-size: 28rpx;
box-sizing: border-box;
}
}
}
}
.footer-bar {
position: fixed;
bottom: 0;
left: 0;
right: 0;
padding: 20rpx 30rpx 40rpx;
background: #fff;
box-shadow: 0 -2rpx 20rpx rgba(0, 0, 0, 0.05);
.save-btn {
height: 88rpx;
background: linear-gradient(135deg, #ff8f0d 0%, #ffb347 100%);
border-radius: 44rpx;
display: flex;
align-items: center;
justify-content: center;
font-size: 32rpx;
font-weight: 600;
color: #fff;
}
}
</style>