个人设置、系统设置

This commit is contained in:
陈红丽 2024-11-13 18:02:28 +08:00
parent 3a7c381580
commit 18d128b84c
13 changed files with 662 additions and 476 deletions

View File

@ -0,0 +1,117 @@
<template>
<n-popover :trigger="trigger" v-model:visible="visible">
<template #trigger>
<slot name="iconSelect"></slot>
</template>
<n-input v-model:value="searchValue" placeholder="输入英文关键词进行搜索" @change="filterIcon" />
<div class="icon-box" style="width: 400px;">
<div v-for="(item, index) in iconArr" :key="index" @click="handleClick(item)" class="icon-content"
:style="{ background: icon === item ? '#268961' : '' }">
<component :is="iconComponent(item)" />
</div>
</div>
</n-popover>
</template>
<script lang="ts">
import { defineComponent, ref, watch } from 'vue'
import * as VueIcon from '@vicons/antd';
import { renderIcon } from '@/utils';
export default defineComponent({
name: "IconPicker",
props: {
icon: {
type: String,
required: true
},
//
trigger: {
type: String,
default: 'click',
validator: function (value) {
return ['click', 'hover', 'focus'].indexOf(value) !== -1
}
}
},
setup(props, context) {
const icons = Object.keys(VueIcon)
const iconArr = ref(icons)
const visible = ref<boolean>(false)
const searchValue = ref('')
const handleClick = (icon) => {
context.emit('update:icon', icon)
visible.value = false;
}
/**
* 进行搜索过滤
*/
const filterIcon = () => {
if (searchValue.value) {
iconArr.value = icons.filter(item => item.toLowerCase().includes(searchValue.value.toLowerCase()))
} else {
iconArr.value = icons;
}
}
const iconComponent = (icon) => {
const IconComponent = renderIcon(VueIcon[icon]);
return IconComponent;
}
watch(visible, () => {
searchValue.value = ''
iconArr.value = icons
})
return {
visible,
icons,
iconArr,
handleClick,
searchValue,
filterIcon,
iconComponent
}
}
})
</script>
<style scoped>
.icon-box {
overflow: auto;
font-size: 20px;
width: 250px;
height: 230px;
display: flex;
flex-wrap: wrap;
flex-direction: row;
align-content: flex-start;
justify-content: center;
}
.icon-content {
width: 45px;
height: 40px;
margin: 5px;
cursor: pointer;
text-align: center;
border-radius: 6px;
border: 1px solid #ccc
}
.icon-content:hover {
background: #1890ff;
}
</style>

View File

@ -0,0 +1,66 @@
<template>
<n-input
v-model:value="inputValue"
:placeholder="placeholder"
allow-clear
@blur="inputBlur"
:max-length="maxlength"
@change="inputF"
/>
</template>
<script lang="ts" setup>
import {computed} from "vue";
const props = defineProps({
modelValue: {
default: ""
},
maxlength: {
default: 50
},
zh: {
default: false
},
isMax: {
default: false
},
maxNum:{
default: 0
},
placeholder:{
default: '请输入'
},
});
const inputF = (value) =>{
console.log(value)
let filterValue=value.replace(/[^0-9]/g,'')?(props.zh?parseInt(value.replace(/[^0-9]/g,'')):value.replace(/[^0-9]/g,'')):''
if(props.isMax){
if(!props.maxNum&&filterValue){
filterValue=0
}else if(props.maxNum&&filterValue&&filterValue> props.maxNum){
filterValue=props.maxNum
}
}
inputValue.value=filterValue
}
const emit = defineEmits<{
(event: 'update:modelValue', value: any): void,
(event: 'blur'): void,
}>()
const inputBlur = ()=>{
emit('blur')
}
const inputValue = computed({
get() {
return props.modelValue
},
set(value) {
emit('update:modelValue', value)
}
})
</script>

View File

@ -4,11 +4,13 @@
*/
import { App } from 'vue';
import { PageWrapper, PageFooter } from '@/components/Page';
import NumberInput from '@/components/numberInput/index.vue';
import { basicModal } from '@/components/Modal';
import { Authority } from '@/components/Authority';
export function setupCustomComponents(app: App) {
app.component('PageWrapper', PageWrapper);
app.component('NumberInput', NumberInput);
app.component('basicModal', basicModal);
app.component('PageFooter', PageFooter);
app.component('Authority', Authority);

View File

@ -1,71 +0,0 @@
<template>
<n-grid cols="1 s:1 m:1 l:4 xl:4 2xl:4" responsive="screen">
<n-grid-item>
<n-form :label-width="80" :model="formValue" :rules="rules" ref="formRef">
<n-form-item label="昵称" path="name">
<n-input v-model:value="formValue.name" placeholder="请输入昵称" />
</n-form-item>
<n-form-item label="邮箱" path="email">
<n-input placeholder="请输入邮箱" v-model:value="formValue.email" />
</n-form-item>
<n-form-item label="联系电话" path="mobile">
<n-input placeholder="请输入联系电话" v-model:value="formValue.mobile" />
</n-form-item>
<n-form-item label="联系地址" path="address">
<n-input v-model:value="formValue.address" type="textarea" placeholder="请输入联系地址" />
</n-form-item>
<div>
<n-space>
<n-button type="primary" @click="formSubmit">更新基本信息</n-button>
</n-space>
</div>
</n-form>
</n-grid-item>
</n-grid>
</template>
<script lang="ts" setup>
import { reactive, ref } from 'vue';
import { FormRules, useMessage } from 'naive-ui';
const rules: FormRules = {
name: {
required: true,
message: '请输入昵称',
trigger: 'blur',
},
email: {
required: true,
message: '请输入邮箱',
trigger: 'blur',
},
mobile: {
required: true,
message: '请输入联系电话',
trigger: 'input',
},
};
const formRef: any = ref(null);
const message = useMessage();
const formValue = reactive({
name: '',
mobile: '',
email: '',
address: '',
});
function formSubmit() {
formRef.value.validate((errors) => {
if (!errors) {
message.success('验证成功');
} else {
message.error('验证失败,请填写完整信息');
}
});
}
</script>

View File

@ -0,0 +1,241 @@
<template>
<div>
<n-form label-width="85px" :model="formData" ref="formRef">
<n-form-item
v-for="(item, index) in configItemList.filter((item) => item.type != 'hidden')"
:key="index"
:label="`${item.name}`"
:path="item.code"
label-placement="left"
>
<template
v-if="
item.type == 'text' ||
item.type == 'readonly' ||
item.type == 'textarea' ||
item.type == 'password'
"
>
<n-input
v-model:value="formData[item.code]"
:placeholder="`请输入${item.name}`"
:type="
item.type == 'textarea' ? 'textarea' : item.type == 'password' ? 'password' : ''
"
:readonly="item.type == 'readonly'"
/>
</template>
<template v-else-if="item.type == 'number'">
<n-input-number v-model:value="formData[item.code]" placeholder="请输入" />
</template>
<!-- <template v-else-if="item.type=='icon'">
<IconPicker class="flex-1" v-model="formData[item.code]"/>
</template> -->
<template v-else-if="item.type == 'radio'">
<n-radio-group v-model:value="formData[item.code]" :path="item.code">
<n-radio v-for="(value, key) in item.param" :value="key" :key="key">
{{ value }}
</n-radio>
</n-radio-group>
</template>
<template v-else-if="item.type == 'checkbox'">
<n-checkbox-group v-model:value="formData[item.code]" :path="item.code">
<n-checkbox :value="key" :key="key" v-for="(value, key) in item.param">{{
value
}}</n-checkbox>
</n-checkbox-group>
</template>
<template v-else-if="item.type == 'select' || item.type == 'selects'">
<n-select
v-model:value="formData[item.code]"
:multiple="item.type == 'selects' ? true: false"
:options="item.param"
>
</n-select>
</template>
<template v-else-if="item.type == 'date' || item.type == 'datetime'">
<n-date-picker
:type="item.type"
:placeholder="`请选择${item.name}`"
v-model:value="formData[item.code]"
style="width: 100%"
:value-format="item.type == 'date' ? 'yyyy-MM-dd' : 'yyyy-MM-dd HH:mm:ss'"
:format="item.type == 'date' ? 'yyyy-MM-dd' : 'yyyy-MM-dd HH:mm:ss'"
/>
</template>
<template v-else-if="item.type == 'image'">
<UploadImg
:fileType="['image/jpeg', 'image/png', 'image/jpg', 'image/gif']"
name="setting"
:fileSize="200"
v-model:image-url="formData[item.code]"
>
<template #tip>支持扩展名: jpg png jpeg;文件大小不超过200M</template>
</UploadImg>
</template>
<template v-else-if="item.type == 'images'">
<UploadImgs
@upload="fileUploadImgs"
file-type=".jpeg,.png,.jpg,.gif"
name="setting"
:fileSize="200"
:multiple="true"
:fileLists="item.filePath"
:z-index="index"
/>
</template>
<template v-else-if="item.type == 'file'">
<UploadFile
@upload="fileUploadFile"
file-type=".xlsx.xls.doc.docx"
name="setting"
:fileLists="formData[item.code] ? [{ name: item.fileName, url: item.filePath }] : []"
:z-index="index"
/>
</template>
<template v-else-if="item.type == 'files'">
<UploadFile
@upload="fileUploadFiles"
file-type=".xlsx.xls.doc.docx"
name="setting"
:multiple="true"
:fileLists="item.filePath"
:z-index="index"
/>
</template>
<template v-else-if="item.type == 'ueditor'">
<Editor ref="editorRef" :height="fwbHeight" class="flex-1" name="config" />
</template>
</n-form-item>
</n-form>
<div class="submit-btn">
<n-button type="primary" @click="handleSubmit" v-perm="['sys:configWeb:save']"
>更新系统设置</n-button
>
</div>
</div>
</template>
<script lang="ts" setup>
import { reactive, ref, onMounted, nextTick } from 'vue';
import { useMessage } from 'naive-ui';
import Editor from '@/components/Editor/tinymce.vue';
import UploadImg from '@/components/Upload/Image.vue';
import UploadImgs from '@/components/Upload/Images.vue';
import UploadFile from '@/components/Upload/file.vue';
import { updateWeb } from '@/api/setting/web';
/**
* 定义接收的参数
*/
const props = defineProps({
dataList: {
type: Array,
required: true,
default: [],
},
activeName: {
type: String,
required: true,
default: '',
},
});
/**
* 定义参数变量
*/
const message = useMessage();
const editorRef = ref();
const formRef = ref();
const fwbHeight = document.body.clientHeight - 400;
const formData = reactive({});
const configItemList = ref([]);
const emit = defineEmits(['success']);
/**
* 执行提交表单
*/
const handleSubmit = async () => {
await formRef.value?.validate();
let ueditorIndex = 0;
configItemList.value.map((item) => {
if (item.type == 'ueditor') {
formData[item.code] = editorRef.value[ueditorIndex].myValue;
ueditorIndex++;
}
});
console.log(formData);
await updateWeb(formData);
message.success('更新成功');
emit('success', props.activeName);
};
/**
* 上传图片文件
* @param list 列表
* @param index 索引
*/
const fileUploadImgs = (list: any, index: any) => {
const code = configItemList.value[index].code;
formData[code] = [];
configItemList.value[index].filePath = [];
list.map((item) => {
formData[code].push(item.filePath);
configItemList.value[index].filePath.push({ filePath: item.filePath });
});
};
/**
* 上传文件
* @param filePath 文件路径
* @param fileName 文件名称
* @param index 索引
*/
const fileUploadFile = async (filePath: any, fileName: any, index: any) => {
const code = configItemList.value[index].code;
formData[code] = filePath ? `${fileName}|${filePath}` : '';
configItemList.value[index].filePath = filePath;
configItemList.value[index].fileName = fileName;
};
/**
* 批量上传文件
* @param list 列表
* @param index 索引
*/
const fileUploadFiles = (list: any, index: any) => {
const code = configItemList.value[index].code;
configItemList.value[index].filePath = [];
formData[code] = [];
list.map((item) => {
formData[code].push(`${item.name}|${item.url}`);
configItemList.value[index].filePath.push({ name: item.name, url: item.url });
});
};
/**
* 钩子函数
*/
onMounted(() => {
configItemList.value = JSON.parse(JSON.stringify(props.dataList));
nextTick(() => {
let ueditorIndex = 0;
configItemList.value.map((item) => {
formData[item.code] = item.value;
if (item.type == 'ueditor') {
if (editorRef.value) {
editorRef.value[ueditorIndex].myValue = item.value;
ueditorIndex++;
}
}
});
});
});
</script>
<style lang="less" scoped>
.submit-btn {
position: fixed;
bottom: 50px;
right: 4%;
}
</style>

View File

@ -0,0 +1,116 @@
<template>
<PageWrapper>
<n-card shadow="never" size="small" class="proCard tabsCard">
<n-tabs v-model="activeName" v-if="tabData.length > 0">
<n-tab-pane
:name="item.configName"
:tab="item.configName"
v-for="(item, index) in tabData"
:key="index"
>
<BasicSetting
:dataList="item.dataList"
v-if="activeName == item.configName"
@success="getReshTabData"
:activeName="activeName"
/>
</n-tab-pane>
</n-tabs>
</n-card>
</PageWrapper>
</template>
<script lang="ts" setup>
import { ref, onMounted } from 'vue';
import { getWebInfo } from '@/api/setting/web';
import { PageWrapper } from '@/components/Page';
import BasicSetting from './BasicSetting.vue';
const activeName = ref();
const tabData = ref([]);
/**
* 获取TAB数据
*/
const getTabData = async (name) => {
let res = await getWebInfo();
res.map((item) => {
item.dataList.map((sub) => {
if (sub.type == 'checkbox' || sub.type == 'selects') {
const values = sub.value.split(',');
sub.value = values;
console.log(values)
}
if (sub.type == 'select' || sub.type == 'selects') {
const arrs = Object.entries(sub.param).map(([key, value]) => ({ label: value, value:key }));
sub.param = arrs
console.log(arrs)
}
if (sub.type == 'images') {
sub.filePath = [];
sub.value = [];
if (sub.valueList && sub.valueList.length) {
sub.valueList.map((path) => {
sub.filePath.push({ url:path,filePath: path });
sub.value.push(path);
});
}
}
if (sub.type == 'file') {
let files = sub.value?.split('|');
sub.fileName = files[0];
sub.filePath = files[1];
}
if (sub.type == 'files') {
sub.filePath = [];
sub.value = [];
if (sub.valueList && sub.valueList.length) {
sub.valueList.map((path) => {
let files = path.split('|');
sub.filePath.push({ name: files[0], url: files[1] });
sub.value.push(`${files[0]}|${files[1]}`);
});
}
}
});
});
tabData.value = res;
activeName.value = name ? name : tabData.value[0].configName;
};
/**
* 刷新TAB数据
*/
const getReshTabData = (name) => {
getTabData(name);
};
/**
* 钩子函数
*/
onMounted(() => {
getTabData();
});
</script>
<style lang="less" scoped>
.thing-cell {
margin: 0 -16px 10px;
padding: 5px 16px;
&:hover {
background: #f3f3f3;
cursor: pointer;
}
}
.thing-cell-on {
background: #f0faff;
color: #165dff;
:deep(.n-thing-main .n-thing-header .n-thing-header__title) {
color: #165dff;
}
&:hover {
background: #f0faff;
}
}
</style>

View File

@ -0,0 +1,120 @@
<template>
<n-form :label-width="80" :model="formData" ref="formRef" label-placement="left">
<div class="flex">
<n-form-item label="名称" path="realname" class="flex-1"
:rule="{ required: true, message: '请输入名称', trigger: 'blur' }">
<n-input v-model:value="formData.realname" placeholder="请输入名称" clearable />
</n-form-item>
<n-form-item label="性别" path="sex" class="flex-1">
<n-radio-group v-model:value="formData.gender" name="gender">
<n-radio :value="1"></n-radio>
<n-radio :value="2"></n-radio>
<n-radio :value="3">保密</n-radio>
</n-radio-group>
</n-form-item>
</div>
<div class="flex">
<n-form-item label="手机号码" path="mobile" class="flex-1" :rule="[
{ required: true, message: '请输入手机号码', trigger: 'blur' },
{ validator: rule.validatePhone, trigger: 'blur' },
]">
<n-input v-model:value="formData.mobile" placeholder="请输入手机号码" clearable />
</n-form-item>
<n-form-item label="邮箱地址" path="email" class="flex-1" :rule="[
{ required: true, message: '请输入邮箱地址', trigger: 'blur' },
{ type: 'email', message: '请输入正确邮箱地址', trigger: 'blur' },
]">
<n-input v-model:value="formData.email" placeholder="请输入邮箱地址" clearable />
</n-form-item>
</div>
<div class="flex">
<n-form-item label="所属区域" class="flex-1" path="city"
:rule="{ type: 'array', required: true, message: '请选择所属区域', trigger: 'change' }">
<chinaArea style="width: 100%" :type="4" v-model="formData.city" />
</n-form-item>
<n-form-item label="详细地址" class="flex-1" path="address"
:rule="{ required: true, message: '请输入详细地址', trigger: 'blur' }">
<n-input v-model:value="formData.address" placeholder="请输入详细地址" clearable />
</n-form-item>
</div>
<div class="flex">
<n-form-item label="简介" path="intro" class="flex-1">
<n-input v-model:value="formData.intro" type="textarea" placeholder="请输入简介" clearable />
</n-form-item>
<n-form-item label="备注" path="note" class="flex-1">
<n-input v-model:value="formData.note" type="textarea" placeholder="请输入备注" clearable />
</n-form-item>
</div>
<n-form-item label="头像" path="avatar" :rule="{ required: true, message: '请上传头像', trigger: 'blur' }">
<UploadImg @change-file-name="(name) => (formData.avatarName = name)"
:fileType="['image/jpeg', 'image/png', 'image/jpg', 'image/gif']" name="user" :fileSize="200"
v-model:image-url="formData.avatar">
<template #tip>支持扩展名: jpg png jpeg;文件大小不超过200M</template>
</UploadImg>
</n-form-item>
<n-form-item style="margin-left: 85px;" v-perm="['sys:profile:update']">
<n-space>
<n-button :loading="subLoading" type="primary" @click="submit">更新基本信息</n-button>
</n-space>
</n-form-item>
</n-form>
</template>
<script lang="ts" setup>
import { reactive, ref, onMounted } from 'vue';
import { FormRules, useMessage } from 'naive-ui';
import { rule } from '@/utils/validate';
import chinaArea from '@/components/ChinaArea/index.vue';
import UploadImg from '@/components/Upload/Image.vue';
import { message } from 'naive-ui';
import { useLockFn } from '@/utils/useLockFn';
import { getUserInfo } from '@/api/system/user';
import { updateProfile } from '@/api/setting/profile';
const formRef: any = ref(null);
const message = useMessage();
/**
* 定义表单参数
*/
const formData = reactive({
realname: '',
gender: '',
avatar: '',
mobile: '',
email: '',
city: [],
address: '',
intro: '',
note: '',
avatarName: '',
});
/**
* 执行提交表单
*/
const handleSubmit = async () => {
await formRef.value?.validate();
await updateProfile(formData);
message.success('更新成功');
};
const { isLock: subLoading, lockFn: submit } = useLockFn(handleSubmit);
/**
* 获取用户信息
*/
const getUserDetail = async () => {
const data = await getUserInfo();
for (const key in formData) {
if (data[key] != null && data[key] != undefined) {
formData[key] = data[key];
}
}
};
/**
* 钩子函数
*/
onMounted(() => {
getUserDetail();
});
</script>

View File

@ -5,7 +5,6 @@
<n-tab-pane name="basic" tab="基本设置">
<BasicSetting />
</n-tab-pane>
<n-tab-pane name="safety" tab="安全设置"><SafetySetting /></n-tab-pane>
</n-tabs>
</n-card>
</PageWrapper>

View File

@ -1,114 +0,0 @@
<template>
<n-grid cols="1 s:1 m:1 l:4 xl:4 2xl:4" responsive="screen">
<n-grid-item>
<n-form :label-width="80" :model="formValue" :rules="rules" ref="formRef">
<n-form-item label="网站名称" path="name">
<n-input v-model:value="formValue.name" placeholder="请输入网站名称" />
</n-form-item>
<n-form-item label="备案编号" path="icpCode">
<n-input placeholder="请输入备案编号" v-model:value="formValue.icpCode" />
</n-form-item>
<n-form-item label="联系电话" path="mobile">
<n-input placeholder="请输入联系电话" v-model:value="formValue.mobile" />
</n-form-item>
<n-form-item label="联系地址" path="address">
<n-input v-model:value="formValue.address" type="textarea" placeholder="请输入联系地址" />
</n-form-item>
<n-form-item label="登录验证码" path="loginCode">
<n-radio-group v-model:value="formValue.loginCode" name="loginCode">
<n-space>
<n-radio :value="1">开启</n-radio>
<n-radio :value="0">关闭</n-radio>
</n-space>
</n-radio-group>
</n-form-item>
<n-form-item label="网站开启访问" path="systemOpen">
<n-switch
size="large"
v-model:value="formValue.systemOpen"
@update:value="systemOpenChange"
/>
</n-form-item>
<n-form-item label="网站关闭提示" path="closeText">
<n-input
v-model:value="formValue.closeText"
type="textarea"
placeholder="请输入网站关闭提示"
/>
</n-form-item>
<div>
<n-space>
<n-button type="primary" @click="formSubmit">更新基本信息</n-button>
</n-space>
</div>
</n-form>
</n-grid-item>
</n-grid>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
import { useDialog, useMessage } from 'naive-ui';
const rules = {
name: {
required: true,
message: '请输入网站名称',
trigger: 'blur',
},
mobile: {
required: true,
message: '请输入联系电话',
trigger: 'input',
},
};
const formRef = ref();
const message = useMessage();
const dialog = useDialog();
const formValue = ref({
name: '',
mobile: '',
icpCode: '',
address: '',
loginCode: 0,
closeText:
'网站维护中,暂时无法访问!本网站正在进行系统维护和技术升级,网站暂时无法访问,敬请谅解!',
systemOpen: true,
});
function systemOpenChange(value) {
if (!value) {
dialog.warning({
title: '提示',
content: '您确定要关闭系统访问吗?该操作立马生效,请慎重操作!',
positiveText: '确定',
negativeText: '取消',
onPositiveClick: () => {
message.success('操作成功');
},
onNegativeClick: () => {
formValue.value.systemOpen = true;
},
});
}
}
function formSubmit() {
formRef.value.validate((errors) => {
if (!errors) {
message.success('验证成功');
} else {
message.error('验证失败,请填写完整信息');
}
});
}
</script>

View File

@ -1,67 +0,0 @@
<template>
<n-grid cols="1 s:1 m:1 l:4 xl:4 2xl:4" responsive="screen">
<n-grid-item>
<n-form :label-width="120" :model="formValue" :rules="rules" ref="formRef">
<n-form-item label="发件人邮箱" path="originator">
<n-input v-model:value="formValue.originator" placeholder="请输入发件人邮箱" />
</n-form-item>
<n-form-item label="SMTP服务器地址">
<n-input placeholder="请输入SMTP服务器地址" />
</n-form-item>
<n-form-item label="SMTP服务器端口">
<n-input placeholder="请输入SMTP服务器端口" />
</n-form-item>
<n-form-item label="SMTP用户名">
<n-input placeholder="请输入SMTP用户名" />
</n-form-item>
<n-form-item label="SMTP密码">
<n-input type="password" placeholder="请输入SMTP密码" />
</n-form-item>
<n-form-item label="邮件测试">
<n-button>邮件测试</n-button>
</n-form-item>
<div>
<n-space>
<n-button type="primary" @click="formSubmit">更新邮件信息</n-button>
</n-space>
</div>
</n-form>
</n-grid-item>
</n-grid>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
import { useMessage } from 'naive-ui';
const rules = {
originator: {
required: true,
message: '请输入发件人邮箱',
trigger: 'blur',
},
};
const formRef = ref();
const message = useMessage();
const formValue = ref({
originator: '',
});
function formSubmit() {
formRef.value.validate((errors) => {
if (!errors) {
message.success('验证成功');
} else {
message.error('验证失败,请填写完整信息');
}
});
}
</script>

View File

@ -1,180 +0,0 @@
<template>
<n-grid cols="1 s:1 m:1 l:4 xl:4 2xl:4" responsive="screen">
<n-grid-item>
<n-form :label-width="120" :model="formValue" :rules="rules" ref="formRef">
<n-form-item label="商品图片(大)">
<n-space align="center">
<span>宽度</span>
<n-input
v-model:value="formValue.bigWidth"
style="width: 80px"
placeholder="宽度像素"
/>
<span>高度</span>
<n-input
v-model:value="formValue.bigHeight"
style="width: 80px"
placeholder="高度像素"
/>
</n-space>
</n-form-item>
<n-form-item label="商品图片(小)">
<n-space align="center">
<span>宽度</span>
<n-input
v-model:value="formValue.smallWidth"
style="width: 80px"
placeholder="宽度像素"
/>
<span>高度</span>
<n-input
v-model:value="formValue.smallHeight"
style="width: 80px"
placeholder="高度像素"
/>
</n-space>
</n-form-item>
<n-form-item label="水印透明度" path="watermarkClarity">
<n-input-number
v-model:value="formValue.watermarkClarity"
:show-button="false"
placeholder="请输入水印透明度"
/>
</n-form-item>
<n-form-item label="水印图片" path="watermarkClarity">
<n-upload action="http://www.mocky.io/v2/5e4bafc63100007100d8b70f">
<n-button>上传文件</n-button>
</n-upload>
</n-form-item>
<n-form-item label="水印位置" path="watermarkPlace">
<n-select
placeholder="请选择价格精确方式"
:options="watermarkPlaceList"
v-model:value="formValue.watermarkPlace"
/>
</n-form-item>
<n-form-item label="价格精确位数" path="pricePreciseNum">
<n-select
placeholder="请选择价格精确位数"
:options="pricePreciseNumList"
v-model:value="formValue.pricePreciseNum"
/>
</n-form-item>
<n-form-item label="价格精确方式" path="pricePrecise">
<n-select
placeholder="请选择价格精确方式"
:options="pricePreciseList"
v-model:value="formValue.pricePrecise"
/>
</n-form-item>
<n-form-item label="前台显示市场价" path="isMarketPrice">
<n-switch size="large" v-model:value="formValue.isMarketPrice" />
</n-form-item>
<div>
<n-space>
<n-button type="primary" @click="formSubmit">更新显示信息</n-button>
</n-space>
</div>
</n-form>
</n-grid-item>
</n-grid>
</template>
<script lang="ts" setup>
import { reactive, ref } from 'vue';
import { FormRules, useMessage } from 'naive-ui';
const rules: FormRules = {
name: {
required: true,
message: '请输入网站名称',
trigger: 'blur',
},
mobile: {
required: true,
message: '请输入联系电话',
trigger: 'input',
},
};
const watermarkPlaceList = [
{
label: '左上',
value: 1,
},
{
label: '右上',
value: 2,
},
{
label: '居中',
value: 3,
},
{
label: '右下',
value: 4,
},
];
const pricePreciseNumList = [
{
label: '2位',
value: 1,
},
{
label: '3位',
value: 2,
},
{
label: '4位',
value: 3,
},
];
const pricePreciseList = [
{
label: '四舍五入',
value: 1,
},
{
label: '向上取整',
value: 2,
},
{
label: '向下取整',
value: 3,
},
];
const formRef: any = ref(null);
const message = useMessage();
const formValue = reactive({
bigWidth: '',
bigHeight: '',
smallWidth: '',
smallHeight: '',
watermarkClarity: null,
pricePrecise: 1,
isMarketPrice: true,
pricePreciseNum: null,
systemOpen: false,
watermarkPlace: null,
});
function formSubmit() {
formRef.value.validate((errors) => {
if (!errors) {
message.success('验证成功');
} else {
message.error('验证失败,请填写完整信息');
}
});
}
</script>

View File

@ -1,43 +0,0 @@
<template>
<PageWrapper>
<n-card :bordered="false" size="small" class="proCard tabsCard">
<n-tabs type="line" size="large">
<n-tab-pane name="basic" tab="基本设置">
<BasicSetting />
</n-tab-pane>
<n-tab-pane name="reveal" tab="显示设置"><RevealSetting /></n-tab-pane>
<n-tab-pane name="email" tab="邮件设置"><EmailSetting /></n-tab-pane>
</n-tabs>
</n-card>
</PageWrapper>
</template>
<script lang="ts" setup>
import { PageWrapper } from '@/components/Page';
import BasicSetting from './BasicSetting.vue';
import RevealSetting from './RevealSetting.vue';
import EmailSetting from './EmailSetting.vue';
</script>
<style lang="less" scoped>
.thing-cell {
margin: 0 -16px 10px;
padding: 5px 16px;
&:hover {
background: #f3f3f3;
cursor: pointer;
}
}
.thing-cell-on {
background: #f0faff;
color: #2d8cf0;
:deep(.n-thing-main .n-thing-header .n-thing-header__title) {
color: #2d8cf0;
}
&:hover {
background: #f0faff;
}
}
</style>