330 lines
15 KiB
Plaintext
330 lines
15 KiB
Plaintext
<template>
|
||
<view class="system-settings-page">
|
||
<view class="settings-card">
|
||
<!-- 顶部导航标签 (1:1 复刻 CRMEB: 横向排列) -->
|
||
<view class="tabs-container">
|
||
<scroll-view class="tabs-scroll" scroll-x="true" show-scrollbar="false" :enable-flex="true">
|
||
<view class="tabs-bar">
|
||
<view
|
||
v-for="(tab, index) in tabs"
|
||
:key="index"
|
||
class="tab-item"
|
||
:class="{ active: currentTab === index }"
|
||
@click="currentTab = index"
|
||
>
|
||
<text class="tab-text">{{ tab.name }}</text>
|
||
<view class="tab-line" v-if="currentTab === index"></view>
|
||
</view>
|
||
</view>
|
||
</scroll-view>
|
||
</view>
|
||
|
||
<!-- 表单区域 -->
|
||
<view class="form-container">
|
||
|
||
<!-- 1. 基础配置 -->
|
||
<view v-if="currentTab === 0" class="form-content">
|
||
<view class="form-item">
|
||
<view class="form-label">站点开启:</view>
|
||
<view class="form-right">
|
||
<radio-group class="radio-group" @change="formData.site_open = parseInt(($event.detail.value as string))">
|
||
<label class="radio-label"><radio value="1" :checked="formData.site_open == 1" color="#1890ff" />开启</label>
|
||
<label class="radio-label"><radio value="0" :checked="formData.site_open == 0" color="#1890ff" />关闭</label>
|
||
</radio-group>
|
||
<view class="form-tip">站点开启/关闭(用于升级等临时关闭),关闭后前端会弹窗显示站点升级中,请稍后访问</view>
|
||
</view>
|
||
</view>
|
||
<view class="form-item">
|
||
<view class="form-label">网站名称:</view>
|
||
<view class="form-right">
|
||
<input class="form-input" v-model="formData.site_name" placeholder="请输入网站名称" />
|
||
<view class="form-tip">网站名称很多地方会显示的,建议认真填写</view>
|
||
</view>
|
||
</view>
|
||
<view class="form-item">
|
||
<view class="form-label">网站地址:</view>
|
||
<view class="form-right">
|
||
<input class="form-input" v-model="formData.site_url" placeholder="请输入网站地址" />
|
||
<view class="form-tip">安装自动配置,不要轻易修改,更换后会影响网站访问、接口请求、本地文件储存、支付回调、微信授权、支付、小程序图片访问、部分二维码、官方授权等</view>
|
||
</view>
|
||
</view>
|
||
<view class="form-item">
|
||
<view class="form-label">消息队列:</view>
|
||
<view class="form-right">
|
||
<radio-group class="radio-group" @change="formData.msg_queue = parseInt(($event.detail.value as string))">
|
||
<label class="radio-label"><radio value="1" :checked="formData.msg_queue == 1" color="#1890ff" />开启</label>
|
||
<label class="radio-label"><radio value="0" :checked="formData.msg_queue == 0" color="#1890ff" />关闭</label>
|
||
</radio-group>
|
||
<view class="form-tip">是否启用消息队列,启用后提升程序运行速度,启用前必须配置Redis缓存,文档地址:https://doc.crmeb.com/single/crmeb_v4/7217</view>
|
||
</view>
|
||
</view>
|
||
<view class="form-item">
|
||
<view class="form-label">联系电话:</view>
|
||
<view class="form-right">
|
||
<input class="form-input" v-model="formData.contact_phone" placeholder="请输入联系电话" />
|
||
<view class="form-tip">联系电话</view>
|
||
</view>
|
||
</view>
|
||
<view class="form-item">
|
||
<view class="form-label">授权密钥:</view>
|
||
<view class="form-right">
|
||
<input class="form-input" v-model="formData.auth_key" placeholder="请输入授权密钥" />
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 2. 分享配置 -->
|
||
<view v-else-if="currentTab === 1" class="form-content">
|
||
<view class="form-item">
|
||
<view class="form-label">分享图片:</view>
|
||
<view class="form-right">
|
||
<view class="upload-placeholder" @click="handleUpload('share_img')">上传图片</view>
|
||
<view class="form-tip">分享图片比例5:4,建议小于50KB</view>
|
||
</view>
|
||
</view>
|
||
<view class="form-item">
|
||
<view class="form-label">分享标题:</view>
|
||
<view class="form-right">
|
||
<input class="form-input" v-model="formData.share_title" />
|
||
</view>
|
||
</view>
|
||
<view class="form-item">
|
||
<view class="form-label">分享简介:</view>
|
||
<view class="form-right">
|
||
<textarea class="form-textarea" v-model="formData.share_desc" />
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 3. LOGO配置 -->
|
||
<view v-else-if="currentTab === 2" class="form-content">
|
||
<view class="form-item">
|
||
<view class="form-label">后台登录LOGO:</view>
|
||
<view class="form-right">
|
||
<view class="upload-placeholder" @click="handleUpload('login_logo')">上传截图</view>
|
||
<view class="form-tip">建议尺寸270*75</view>
|
||
</view>
|
||
</view>
|
||
<view class="form-item">
|
||
<view class="form-label">后台小LOGO:</view>
|
||
<view class="form-right">
|
||
<view class="upload-placeholder" @click="handleUpload('small_logo')">上传图片</view>
|
||
<view class="form-tip">建议尺寸180*180</view>
|
||
</view>
|
||
</view>
|
||
<view class="form-item">
|
||
<view class="form-label">后台大LOGO:</view>
|
||
<view class="form-right">
|
||
<view class="upload-placeholder" @click="handleUpload('big_logo')">上传图片</view>
|
||
<view class="form-tip">建议尺寸170*50</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 4. 自定义JS -->
|
||
<view v-else-if="currentTab === 3" class="form-content">
|
||
<view class="form-item">
|
||
<view class="form-label">移动端JS:</view>
|
||
<view class="form-right">
|
||
<textarea class="form-textarea code-bg" v-model="formData.mobile_js" />
|
||
</view>
|
||
</view>
|
||
<view class="form-item">
|
||
<view class="form-label">管理端JS:</view>
|
||
<view class="form-right">
|
||
<textarea class="form-textarea code-bg" v-model="formData.admin_js" />
|
||
</view>
|
||
</view>
|
||
<view class="form-item">
|
||
<view class="form-label">PC端JS:</view>
|
||
<view class="form-right">
|
||
<textarea class="form-textarea code-bg" v-model="formData.pc_js" />
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 5. 地图配置 -->
|
||
<view v-else-if="currentTab === 4" class="form-content">
|
||
<view class="form-item">
|
||
<view class="form-label">腾讯地图KEY:</view>
|
||
<view class="form-right">
|
||
<input class="form-input" v-model="formData.tencent_map_key" />
|
||
<view class="form-tip">申请地址:https://lbs.qq.com</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 6. 备案配置 -->
|
||
<view v-else-if="currentTab === 5" class="form-content">
|
||
<view class="form-item">
|
||
<view class="form-label">备案号:</view>
|
||
<view class="form-right">
|
||
<input class="form-input" v-model="formData.filing_no" />
|
||
</view>
|
||
</view>
|
||
<view class="form-item">
|
||
<view class="form-label">ICP链接:</view>
|
||
<view class="form-right">
|
||
<input class="form-input" v-model="formData.icp_link" />
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 7. 模块配置 -->
|
||
<view v-else-if="currentTab === 6" class="form-content">
|
||
<view class="form-item">
|
||
<view class="form-label">功能开启:</view>
|
||
<view class="form-right">
|
||
<checkbox-group class="checkbox-group" @change="formData.module_config = ($event.detail.value as string[])">
|
||
<label class="checkbox-label"><checkbox value="秒杀" :checked="formData.module_config.includes('秒杀')" color="#1890ff" />秒杀</label>
|
||
<label class="checkbox-label"><checkbox value="砍价" :checked="formData.module_config.includes('砍价')" color="#1890ff" />砍价</label>
|
||
<label class="checkbox-label"><checkbox value="拼团" :checked="formData.module_config.includes('拼团')" color="#1890ff" />拼团</label>
|
||
</checkbox-group>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 8. 远程登录 -->
|
||
<view v-else-if="currentTab === 7" class="form-content">
|
||
<view class="form-item">
|
||
<view class="form-label">远程登录地址:</view>
|
||
<view class="form-right">
|
||
<input class="form-input" v-model="formData.remote_login_url" />
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 9. WAF配置 -->
|
||
<view v-else-if="currentTab === 8" class="form-content">
|
||
<view class="form-item">
|
||
<view class="form-label">WAF类型:</view>
|
||
<view class="form-right">
|
||
<radio-group class="radio-group" @change="formData.waf_type = parseInt(($event.detail.value as string))">
|
||
<label class="radio-label"><radio value="0" :checked="formData.waf_type == 0" color="#1890ff" />关闭</label>
|
||
<label class="radio-label"><radio value="1" :checked="formData.waf_type == 1" color="#1890ff" />拦截</label>
|
||
<label class="radio-label"><radio value="2" :checked="formData.waf_type == 2" color="#1890ff" />过滤</label>
|
||
</radio-group>
|
||
<view class="form-tip">WAF类型:关闭(所有参数都能正常请求),拦截(匹配到WAF配置的参数阻断接口请求),过滤(匹配到WAF配置的参数过滤参数,正常请求接口)</view>
|
||
</view>
|
||
</view>
|
||
<view class="form-item">
|
||
<view class="form-label">WAF配置:</view>
|
||
<view class="form-right">
|
||
<textarea class="form-textarea code-bg waf-textarea" v-model="formData.waf_config" />
|
||
<view class="form-tip">WAF配置验证参数,过滤掉不需要的参数或拦截请求,多个参数用回车换行分隔</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 提交按钮 -->
|
||
<view class="submit-section">
|
||
<view class="form-label"></view> <!-- 占位用于对齐 -->
|
||
<view class="form-right">
|
||
<button class="btn-submit" @click="handleSubmit">提交</button>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script setup lang="uts">
|
||
import { ref } from "vue"
|
||
|
||
const currentTab = ref(0)
|
||
const tabs = [
|
||
{ name: "基础配置" }, { name: "分享配置" }, { name: "LOGO配置" },
|
||
{ name: "自定义JS" }, { name: "地图配置" }, { name: "备案配置" },
|
||
{ name: "模块配置" }, { name: "远程登录配置" }, { name: "WAF配置" }
|
||
]
|
||
|
||
const formData = ref({
|
||
site_open: 1,
|
||
site_name: "CRMEB标准版",
|
||
site_url: "https://v5.crmeb.net",
|
||
msg_queue: 0,
|
||
contact_phone: "",
|
||
auth_key: "AO9azvBW9vEcOH7swklTM0RYRb6EB4RLWMSD88MnKTi8Vd6cjXVd",
|
||
share_img: "",
|
||
share_title: "CRMEB v5标准版",
|
||
share_desc: "完善的文档 全心而来!",
|
||
login_logo: "",
|
||
small_logo: "",
|
||
big_logo: "",
|
||
mobile_js: "",
|
||
admin_js: "",
|
||
pc_js: "",
|
||
tencent_map_key: "SMJBZ-WCHK4-ZPZUA-DSIXI-XDDVQ-XWFX7",
|
||
filing_no: "陕ICP备14011498号-3",
|
||
icp_link: "https://beian.miit.gov.cn/",
|
||
module_config: ["秒杀", "砍价", "拼团"] as string[],
|
||
remote_login_url: "",
|
||
waf_type: 2,
|
||
waf_config: "/\\.\\.\\//\n/\\<\\?/\n/\\bor\\b.*=\\s*\\*/i\n/(select[\\s\\S]*?)(from|limit)/i\n/(union[\\s\\S]*?select)/i\n/(having\\s+updatexml|extractvalue)/i"
|
||
})
|
||
|
||
const handleUpload = (field: string) => {
|
||
uni.showToast({ title: "选择文件: " + field, icon: "none" })
|
||
}
|
||
|
||
const handleSubmit = () => {
|
||
uni.showLoading({ title: "保存中..." })
|
||
setTimeout(() => {
|
||
uni.hideLoading()
|
||
uni.showToast({ title: "保存成功", icon: "success" })
|
||
}, 800)
|
||
}
|
||
</script>
|
||
|
||
<style scoped>
|
||
.system-settings-page { padding: 20px; background-color: #f5f7f9; min-height: 100vh; }
|
||
.settings-card { background-color: #fff; border-radius: 4px; padding: 20px; box-shadow: 0 1px 4px rgba(0,21,41,0.08); }
|
||
|
||
/* 核心修复:确保 Tabs 横向排列并且可以滑动 */
|
||
.tabs-container { margin-bottom: 30px; border-bottom: 1px solid #e8eaec; width: 100%; overflow: hidden; }
|
||
.tabs-scroll { width: 100%; white-space: nowrap; }
|
||
.tabs-bar { display: inline-flex; flex-direction: row; min-width: 100%; }
|
||
|
||
.tab-item {
|
||
display: inline-flex;
|
||
flex-direction: row;
|
||
align-items: center;
|
||
padding: 12px 24px;
|
||
font-size: 14px;
|
||
color: #515a6e;
|
||
position: relative;
|
||
cursor: pointer;
|
||
flex-shrink: 0;
|
||
}
|
||
.tab-item.active { color: #1890ff; font-weight: bold; }
|
||
.tab-line { position: absolute; bottom: 0; left: 0; right: 0; height: 2px; background-color: #1890ff; }
|
||
|
||
.form-container { padding-left: 20px; }
|
||
|
||
/* 核心修复:确保表单项横向排列 (Label left, Input right) */
|
||
.form-item { display: flex; flex-direction: row; margin-bottom: 25px; align-items: flex-start; }
|
||
|
||
.form-label { width: 140px; font-size: 14px; color: #303133; text-align: right; padding-right: 20px; padding-top: 8px; flex-shrink: 0; }
|
||
.form-right { flex: 1; display: flex; flex-direction: column; width: 100%; }
|
||
|
||
.form-input { border: 1px solid #dcdfe6; width: 450px; height: 32px; padding: 0 15px; border-radius: 4px; font-size: 14px; color: #606266; outline: none; transition: border-color .2s; }
|
||
.form-input:focus { border-color: #409eff; }
|
||
|
||
.form-textarea { border: 1px solid #dcdfe6; width: 550px; height: 120px; padding: 10px 15px; border-radius: 4px; font-size: 14px; color: #606266; line-height: 1.6; outline: none; }
|
||
.form-textarea:focus { border-color: #409eff; }
|
||
|
||
.waf-textarea { height: 200px; }
|
||
.code-bg { background-color: #f5f7fa; font-family: "Lucida Console", Monaco, monospace; }
|
||
|
||
.form-tip { font-size: 12px; color: #c0c4cc; margin-top: 8px; line-height: 1.5; width: 550px; }
|
||
|
||
.radio-group, .checkbox-group { display: flex; flex-direction: row; align-items: center; min-height: 32px; }
|
||
.radio-label, .checkbox-label { display: flex; flex-direction: row; align-items: center; margin-right: 30px; font-size: 14px; color: #606266; cursor: pointer; }
|
||
|
||
.upload-placeholder { width: 80px; height: 80px; border: 1px dashed #dcdfe6; border-radius: 4px; display: flex; align-items: center; justify-content: center; font-size: 12px; color: #909399; cursor: pointer; transition: all .2s; }
|
||
.upload-placeholder:hover { border-color: #409eff; color: #409eff; }
|
||
|
||
.submit-section { display: flex; flex-direction: row; margin-top: 20px; padding-top: 10px; }
|
||
.btn-submit { background-color: #1890ff; color: #fff; width: 65px; height: 32px; line-height: 32px; font-size: 14px; border-radius: 4px; margin: 0; border: none; cursor: pointer; text-align: center; }
|
||
.btn-submit:active { background-color: #096dd9; }
|
||
</style> |