529 lines
13 KiB
Plaintext
529 lines
13 KiB
Plaintext
<!-- 系统设置页面 - 基于CRMEB设计 -->
|
||
<template>
|
||
<view class="system-settings">
|
||
<!-- 设置选项卡 -->
|
||
<view class="settings-tabs">
|
||
<view class="tab-list">
|
||
<view
|
||
v-for="tab in settingTabs"
|
||
:key="tab.key"
|
||
class="tab-item"
|
||
:class="{ active: activeTab === tab.key }"
|
||
@click="switchTab(tab.key)"
|
||
>
|
||
<text class="tab-text">{{ tab.label }}</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 基础设置 -->
|
||
<view v-if="activeTab === 'basic'" class="setting-section">
|
||
<view class="section-title">基础设置</view>
|
||
<view class="setting-form">
|
||
<view class="form-item">
|
||
<text class="label">网站名称:</text>
|
||
<input v-model="settings.site_name" placeholder="请输入网站名称" class="input-field" />
|
||
</view>
|
||
<view class="form-item">
|
||
<text class="label">网站域名:</text>
|
||
<input v-model="settings.site_domain" placeholder="请输入网站域名" class="input-field" />
|
||
</view>
|
||
<view class="form-item">
|
||
<text class="label">网站Logo:</text>
|
||
<view class="upload-area">
|
||
<image v-if="settings.site_logo" :src="settings.site_logo" class="logo-preview" />
|
||
<button class="upload-btn" @click="chooseLogo">选择图片</button>
|
||
</view>
|
||
</view>
|
||
<view class="form-item">
|
||
<text class="label">客服电话:</text>
|
||
<input v-model="settings.service_phone" placeholder="请输入客服电话" class="input-field" />
|
||
</view>
|
||
<view class="form-item">
|
||
<text class="label">网站描述:</text>
|
||
<textarea v-model="settings.site_description" placeholder="请输入网站描述" class="textarea-field" />
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 支付设置 -->
|
||
<view v-if="activeTab === 'payment'" class="setting-section">
|
||
<view class="section-title">支付设置</view>
|
||
<view class="setting-form">
|
||
<view class="form-item">
|
||
<text class="label">微信支付:</text>
|
||
<view class="switch-item">
|
||
<switch :checked="settings.wechat_pay_enabled" @change="onWechatPayChange" />
|
||
<text class="switch-label">{{ settings.wechat_pay_enabled ? '已开启' : '已关闭' }}</text>
|
||
</view>
|
||
</view>
|
||
<view v-if="settings.wechat_pay_enabled" class="form-item">
|
||
<text class="label">微信商户号:</text>
|
||
<input v-model="settings.wechat_mch_id" placeholder="请输入微信商户号" class="input-field" />
|
||
</view>
|
||
<view v-if="settings.wechat_pay_enabled" class="form-item">
|
||
<text class="label">微信支付密钥:</text>
|
||
<input v-model="settings.wechat_pay_key" type="password" placeholder="请输入微信支付密钥" class="input-field" />
|
||
</view>
|
||
|
||
<view class="form-item">
|
||
<text class="label">支付宝支付:</text>
|
||
<view class="switch-item">
|
||
<switch :checked="settings.alipay_enabled" @change="onAlipayChange" />
|
||
<text class="switch-label">{{ settings.alipay_enabled ? '已开启' : '已关闭' }}</text>
|
||
</view>
|
||
</view>
|
||
<view v-if="settings.alipay_enabled" class="form-item">
|
||
<text class="label">支付宝应用ID:</text>
|
||
<input v-model="settings.alipay_app_id" placeholder="请输入支付宝应用ID" class="input-field" />
|
||
</view>
|
||
|
||
<view class="form-item">
|
||
<text class="label">余额支付:</text>
|
||
<view class="switch-item">
|
||
<switch :checked="settings.balance_pay_enabled" @change="onBalancePayChange" />
|
||
<text class="switch-label">{{ settings.balance_pay_enabled ? '已开启' : '已关闭' }}</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 物流设置 -->
|
||
<view v-if="activeTab === 'shipping'" class="setting-section">
|
||
<view class="section-title">物流设置</view>
|
||
<view class="setting-form">
|
||
<view class="form-item">
|
||
<text class="label">默认物流公司:</text>
|
||
<picker mode="selector" :range="expressCompanies" range-key="name" @change="onDefaultExpressChange">
|
||
<view class="picker-text">{{ selectedExpress || '选择物流公司' }}</view>
|
||
</picker>
|
||
</view>
|
||
<view class="form-item">
|
||
<text class="label">运费计算方式:</text>
|
||
<picker mode="selector" :range="shippingMethods" range-key="label" @change="onShippingMethodChange">
|
||
<view class="picker-text">{{ selectedShippingMethod || '选择计算方式' }}</view>
|
||
</picker>
|
||
</view>
|
||
<view class="form-item">
|
||
<text class="label">包邮金额:</text>
|
||
<input v-model="settings.free_shipping_amount" type="number" placeholder="请输入包邮金额" class="input-field" />
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 消息设置 -->
|
||
<view v-if="activeTab === 'notification'" class="setting-section">
|
||
<view class="section-title">消息设置</view>
|
||
<view class="setting-form">
|
||
<view class="form-item">
|
||
<text class="label">短信通知:</text>
|
||
<view class="switch-item">
|
||
<switch :checked="settings.sms_enabled" @change="onSmsChange" />
|
||
<text class="switch-label">{{ settings.sms_enabled ? '已开启' : '已关闭' }}</text>
|
||
</view>
|
||
</view>
|
||
<view v-if="settings.sms_enabled" class="form-item">
|
||
<text class="label">短信服务商:</text>
|
||
<picker mode="selector" :range="smsProviders" range-key="label" @change="onSmsProviderChange">
|
||
<view class="picker-text">{{ selectedSmsProvider || '选择服务商' }}</view>
|
||
</picker>
|
||
</view>
|
||
|
||
<view class="form-item">
|
||
<text class="label">邮件通知:</text>
|
||
<view class="switch-item">
|
||
<switch :checked="settings.email_enabled" @change="onEmailChange" />
|
||
<text class="switch-label">{{ settings.email_enabled ? '已开启' : '已关闭' }}</text>
|
||
</view>
|
||
</view>
|
||
<view v-if="settings.email_enabled" class="form-item">
|
||
<text class="label">SMTP服务器:</text>
|
||
<input v-model="settings.smtp_host" placeholder="请输入SMTP服务器" class="input-field" />
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 保存按钮 -->
|
||
<view class="save-section">
|
||
<button class="btn btn-primary" @click="saveSettings">保存设置</button>
|
||
<button class="btn btn-default" @click="resetSettings">重置</button>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script setup lang="uts">
|
||
import { ref, onMounted } from 'vue'
|
||
import supa from '@/components/supadb/aksupainstance.uts'
|
||
|
||
// 响应式数据
|
||
const activeTab = ref('basic')
|
||
|
||
const settingTabs = ref([
|
||
{ key: 'basic', label: '基础设置' },
|
||
{ key: 'payment', label: '支付设置' },
|
||
{ key: 'shipping', label: '物流设置' },
|
||
{ key: 'notification', label: '消息设置' }
|
||
])
|
||
|
||
const settings = ref({
|
||
// 基础设置
|
||
site_name: '',
|
||
site_domain: '',
|
||
site_logo: '',
|
||
service_phone: '',
|
||
site_description: '',
|
||
|
||
// 支付设置
|
||
wechat_pay_enabled: false,
|
||
wechat_mch_id: '',
|
||
wechat_pay_key: '',
|
||
alipay_enabled: false,
|
||
alipay_app_id: '',
|
||
balance_pay_enabled: true,
|
||
|
||
// 物流设置
|
||
default_express: '',
|
||
shipping_method: '',
|
||
free_shipping_amount: '',
|
||
|
||
// 消息设置
|
||
sms_enabled: false,
|
||
sms_provider: '',
|
||
email_enabled: false,
|
||
smtp_host: ''
|
||
})
|
||
|
||
// 选项数据
|
||
const expressCompanies = ref([])
|
||
const shippingMethods = ref([
|
||
{ value: 'fixed', label: '固定运费' },
|
||
{ value: 'weight', label: '按重量计算' },
|
||
{ value: 'pieces', label: '按件数计算' }
|
||
])
|
||
const smsProviders = ref([
|
||
{ value: 'aliyun', label: '阿里云短信' },
|
||
{ value: 'tencent', label: '腾讯云短信' },
|
||
{ value: 'qiniu', label: '七牛云短信' }
|
||
])
|
||
|
||
const selectedExpress = ref('')
|
||
const selectedShippingMethod = ref('')
|
||
const selectedSmsProvider = ref('')
|
||
|
||
// 方法
|
||
const switchTab = (tabKey: string) => {
|
||
activeTab.value = tabKey
|
||
}
|
||
|
||
const onWechatPayChange = (e: any) => {
|
||
settings.value.wechat_pay_enabled = e.detail.value
|
||
}
|
||
|
||
const onAlipayChange = (e: any) => {
|
||
settings.value.alipay_enabled = e.detail.value
|
||
}
|
||
|
||
const onBalancePayChange = (e: any) => {
|
||
settings.value.balance_pay_enabled = e.detail.value
|
||
}
|
||
|
||
const onSmsChange = (e: any) => {
|
||
settings.value.sms_enabled = e.detail.value
|
||
}
|
||
|
||
const onEmailChange = (e: any) => {
|
||
settings.value.email_enabled = e.detail.value
|
||
}
|
||
|
||
const onDefaultExpressChange = (e: any) => {
|
||
selectedExpress.value = expressCompanies.value[e.detail.value].name
|
||
settings.value.default_express = expressCompanies.value[e.detail.value].code
|
||
}
|
||
|
||
const onShippingMethodChange = (e: any) => {
|
||
selectedShippingMethod.value = shippingMethods.value[e.detail.value].label
|
||
settings.value.shipping_method = shippingMethods.value[e.detail.value].value
|
||
}
|
||
|
||
const onSmsProviderChange = (e: any) => {
|
||
selectedSmsProvider.value = smsProviders.value[e.detail.value].label
|
||
settings.value.sms_provider = smsProviders.value[e.detail.value].value
|
||
}
|
||
|
||
const chooseLogo = () => {
|
||
uni.chooseImage({
|
||
count: 1,
|
||
sizeType: ['compressed'],
|
||
sourceType: ['album', 'camera'],
|
||
success: (res) => {
|
||
const tempFilePath = res.tempFilePaths[0]
|
||
// 这里应该上传图片到服务器
|
||
settings.value.site_logo = tempFilePath // 临时显示
|
||
uni.showToast({
|
||
title: '图片选择成功',
|
||
icon: 'success'
|
||
})
|
||
}
|
||
})
|
||
}
|
||
|
||
const saveSettings = async () => {
|
||
try {
|
||
await supa.from('system_settings').upsert(settings.value)
|
||
uni.showToast({
|
||
title: '保存成功',
|
||
icon: 'success'
|
||
})
|
||
} catch (error) {
|
||
console.error('保存设置失败:', error)
|
||
uni.showToast({
|
||
title: '保存失败',
|
||
icon: 'error'
|
||
})
|
||
}
|
||
}
|
||
|
||
const resetSettings = () => {
|
||
loadSettings()
|
||
}
|
||
|
||
// 数据加载方法
|
||
const loadSettings = async () => {
|
||
try {
|
||
const { data } = await supa.from('system_settings').select('*').single()
|
||
if (data) {
|
||
settings.value = { ...settings.value, ...data }
|
||
}
|
||
} catch (error) {
|
||
console.error('加载设置失败:', error)
|
||
}
|
||
}
|
||
|
||
const loadExpressCompanies = async () => {
|
||
try {
|
||
const { data } = await supa.from('express_companies').select('*')
|
||
expressCompanies.value = data || []
|
||
} catch (error) {
|
||
console.error('加载物流公司失败:', error)
|
||
}
|
||
}
|
||
|
||
// 页面初始化
|
||
onMounted(async () => {
|
||
await Promise.all([
|
||
loadSettings(),
|
||
loadExpressCompanies()
|
||
])
|
||
})
|
||
</script>
|
||
|
||
<style lang="scss">
|
||
.system-settings {
|
||
padding: 30rpx;
|
||
background-color: #f5f5f5;
|
||
min-height: 100vh;
|
||
}
|
||
|
||
// 设置选项卡样式
|
||
.settings-tabs {
|
||
background-color: #fff;
|
||
border-radius: 12rpx;
|
||
margin-bottom: 30rpx;
|
||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
|
||
|
||
.tab-list {
|
||
display: flex;
|
||
padding: 0 30rpx;
|
||
}
|
||
|
||
.tab-item {
|
||
flex: 1;
|
||
padding: 30rpx 20rpx;
|
||
text-align: center;
|
||
cursor: pointer;
|
||
transition: all 0.2s;
|
||
|
||
&.active {
|
||
background-color: #007bff;
|
||
color: white;
|
||
}
|
||
|
||
.tab-text {
|
||
font-size: 28rpx;
|
||
color: #495057;
|
||
}
|
||
|
||
&.active .tab-text {
|
||
color: white;
|
||
}
|
||
}
|
||
}
|
||
|
||
// 设置表单样式
|
||
.setting-section {
|
||
background-color: #fff;
|
||
border-radius: 12rpx;
|
||
padding: 30rpx;
|
||
margin-bottom: 30rpx;
|
||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
|
||
|
||
.section-title {
|
||
font-size: 32rpx;
|
||
font-weight: bold;
|
||
color: #212529;
|
||
margin-bottom: 30rpx;
|
||
}
|
||
|
||
.setting-form {
|
||
.form-item {
|
||
display: flex;
|
||
align-items: center;
|
||
margin-bottom: 30rpx;
|
||
|
||
.label {
|
||
font-size: 28rpx;
|
||
color: #666;
|
||
margin-right: 20rpx;
|
||
white-space: nowrap;
|
||
min-width: 150rpx;
|
||
}
|
||
|
||
.input-field {
|
||
flex: 1;
|
||
height: 60rpx;
|
||
border: 1rpx solid #ddd;
|
||
border-radius: 6rpx;
|
||
padding: 0 20rpx;
|
||
font-size: 26rpx;
|
||
}
|
||
|
||
.textarea-field {
|
||
flex: 1;
|
||
min-height: 120rpx;
|
||
border: 1rpx solid #ddd;
|
||
border-radius: 6rpx;
|
||
padding: 20rpx;
|
||
font-size: 26rpx;
|
||
line-height: 1.5;
|
||
}
|
||
|
||
.switch-item {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 20rpx;
|
||
|
||
.switch-label {
|
||
font-size: 26rpx;
|
||
color: #666;
|
||
}
|
||
}
|
||
|
||
.picker-text {
|
||
padding: 0 20rpx;
|
||
height: 60rpx;
|
||
line-height: 60rpx;
|
||
border: 1rpx solid #ddd;
|
||
border-radius: 6rpx;
|
||
font-size: 26rpx;
|
||
color: #333;
|
||
min-width: 200rpx;
|
||
}
|
||
|
||
.upload-area {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 20rpx;
|
||
|
||
.logo-preview {
|
||
width: 80rpx;
|
||
height: 80rpx;
|
||
border-radius: 8rpx;
|
||
object-fit: cover;
|
||
}
|
||
|
||
.upload-btn {
|
||
padding: 12rpx 24rpx;
|
||
border: 1rpx solid #ddd;
|
||
border-radius: 6rpx;
|
||
background-color: #f5f5f5;
|
||
font-size: 26rpx;
|
||
color: #333;
|
||
cursor: pointer;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// 保存按钮区域
|
||
.save-section {
|
||
background-color: #fff;
|
||
border-radius: 12rpx;
|
||
padding: 30rpx;
|
||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
|
||
display: flex;
|
||
gap: 20rpx;
|
||
justify-content: center;
|
||
|
||
.btn {
|
||
padding: 15rpx 40rpx;
|
||
border-radius: 8rpx;
|
||
font-size: 28rpx;
|
||
border: none;
|
||
cursor: pointer;
|
||
|
||
&.btn-primary {
|
||
background-color: #007bff;
|
||
color: white;
|
||
}
|
||
|
||
&.btn-default {
|
||
background-color: #f5f5f5;
|
||
color: #333;
|
||
}
|
||
}
|
||
}
|
||
|
||
// 响应式设计
|
||
@media (max-width: 750rpx) {
|
||
.settings-tabs {
|
||
.tab-list {
|
||
flex-direction: column;
|
||
}
|
||
|
||
.tab-item {
|
||
padding: 20rpx;
|
||
}
|
||
}
|
||
|
||
.form-item {
|
||
flex-direction: column;
|
||
align-items: stretch;
|
||
|
||
.label {
|
||
margin-bottom: 10rpx;
|
||
min-width: auto;
|
||
}
|
||
|
||
.input-field,
|
||
.textarea-field,
|
||
.picker-text {
|
||
width: 100%;
|
||
}
|
||
|
||
.switch-item {
|
||
justify-content: space-between;
|
||
}
|
||
}
|
||
|
||
.save-section {
|
||
flex-direction: column;
|
||
align-items: stretch;
|
||
|
||
.btn {
|
||
width: 100%;
|
||
}
|
||
}
|
||
}
|
||
</style>
|