From 6af033cedb5d85539e8fd3d825604bb4c73e718b Mon Sep 17 00:00:00 2001 From: 陶杰 <1378534974@qq.com> Date: 星期三, 04 十二月 2024 10:17:37 +0800 Subject: [PATCH] 1.常规配置:基本配置 2.登录页:图片、公司名称、备案号、公司logo 3.主体页:图片、公司名称、备案号、公司logo --- pages/login.vue | 54 ++++++ layouts/default.vue | 46 +++++ pages/regular/sys.vue | 339 ++++++++++++++++++++++++++++++++++++++++++ services/base.js | 5 4 files changed, 437 insertions(+), 7 deletions(-) diff --git a/layouts/default.vue b/layouts/default.vue index 7aea5b1..7ab15f6 100644 --- a/layouts/default.vue +++ b/layouts/default.vue @@ -1,16 +1,16 @@ <template> <div class="back-layout"> - <div - v-if="isMobile && !menuShrink" - class="back-layout__backdrop" - @click="onBackdropClick" - /> + <div v-if="isMobile && !menuShrink" class="back-layout__backdrop" @click="onBackdropClick" /> <base-sidebar></base-sidebar> <div class="back-layout__right"> <base-nav></base-nav> <tags-view v-if="enableTagView"></tags-view> <div class="back-layout__main"> <nuxt /> + </div> + <div class="copyright"> + <img class="copyright-logo" :src="logoUrl" /> {{ copyright?.base_website_name }} 版权所有 | + {{ copyright?.base_regisition_num }} </div> </div> </div> @@ -24,9 +24,14 @@ TagsView, }, middleware: ['auth', 'permission'], + created() { + this.getCopyRight() + }, data() { return { enableTagView: this.$config.enableTagView, + copyright: {}, + logoUrl: '', } }, computed: { @@ -39,6 +44,16 @@ onBackdropClick() { this.$store.commit('app/SET_MENU_SHRINK', true) }, + + async getCopyRight() { + const { code, data } = await this.$services.base.getBaseInfo() + if (code === 0) { + this.copyright = data + this.copyright.base_bg_url = JSON.parse(data.base_bg_url || []) + this.copyright.base_logo_url = JSON.parse(data.base_logo_url || []) + this.logoUrl = this.copyright?.base_logo_url[0]?.url + } + }, }, } </script> @@ -49,6 +64,7 @@ height: 100%; overflow: hidden; display: flex; + &__backdrop { background-color: rgba(0, 0, 0, 0.3); width: 100%; @@ -57,6 +73,7 @@ position: absolute; z-index: 999; } + &__right { flex: 1; height: 100%; @@ -65,11 +82,30 @@ display: flex; flex-direction: column; } + &__main { flex: 1; background-color: $bg-color; overflow: auto; padding: 20px; } + + .copyright { + margin: auto; + margin-top: 10px; + height: 20px; + display: flex; + justify-content: center; + align-content: center; + font-size: 12px; + color: gray; + + .copyright-logo { + width: 15px; + height: 15px; + border-radius: 50px; + /* 设置圆角 */ + } + } } </style> diff --git a/pages/login.vue b/pages/login.vue index cdb67cc..10a8104 100644 --- a/pages/login.vue +++ b/pages/login.vue @@ -1,9 +1,18 @@ <template> - <div class="login-page"> + + <div class="login-page" + :style="{ + backgroundImage: 'url(' + bgUrl + ')', + backgroundSize: 'cover', + backgroundPosition: 'center', + height: '100vh' } + " + > <div class="form-content"> <div class="text-22 font-bold text-mainTitle">HELLO</div> <div class="text-26 font-bold text-mainTitle"> - 欢迎来到<span class="text-primary">{{ platformName }}</span> + <!-- 欢迎来到<span class="text-primary">{{ platformName }}</span> --> + 欢迎来到<span class="text-primary">{{ copyright?.base_website_name }}</span> </div> <div class="flex items-center justify-center mt-50 mb-20"> <div @@ -118,8 +127,15 @@ >登录</el-button > </el-form> + + <div class="copyright"> + <img class="copyright-logo" :src="logoUrl" /> {{ copyright?.base_website_name }} 版权所有 | + {{ copyright?.base_regisition_num }} + </div> </div> + </div> + </template> <script> @@ -152,6 +168,9 @@ }, code: { required: true, message: '请输入图形验证码', trigger: 'blur' }, }, + copyright:{}, + logoUrl:'', + bgUrl:'https://hmy-flower.oss-cn-shanghai.aliyuncs.com/87/878c638c06cf4c3080e6b7139f9a955cdshsp.png', } }, watch: { @@ -162,10 +181,22 @@ }, }, async mounted() { + await this.getCopyRight() // 获取验证码图形 await this.getCapacha() }, methods: { + + async getCopyRight() { + const { code, data } = await this.$services.base.getBaseInfo() + if (code === 0) { + this.copyright = data + this.copyright.base_bg_url = JSON.parse(data.base_bg_url || []) + this.copyright.base_logo_url = JSON.parse(data.base_logo_url || []) + this.logoUrl = this.copyright?.base_logo_url[0]?.url + this.bgUrl=this.copyright?.base_bg_url[0]?.url + } + }, async getCapacha() { const { captchaCodeId, imageSrc } = await this.$services.base.createCaptcha() @@ -278,5 +309,24 @@ } } } + + .copyright { + width:100%; + margin: auto; + margin-top: 10px; + height: 20px; + display: flex; + justify-content: center; + align-content: center; + font-size: 12px; + color: gray; + + .copyright-logo { + width: 15px; + height: 15px; + border-radius: 50px; + /* 设置圆角 */ + } + } } </style> diff --git a/pages/regular/sys.vue b/pages/regular/sys.vue new file mode 100644 index 0000000..6c79517 --- /dev/null +++ b/pages/regular/sys.vue @@ -0,0 +1,339 @@ +<template> + <div> + <el-card class="box-card"> + <div slot="header" class="clearfix"> + <span>系统配置</span> + <!-- <el-button style="float: right; padding: 3px 0" type="text">操作按钮</el-button> --> + </div> + + <el-tabs v-model="activeName" type="card" class="setupClass-tab" @tab-click="handleClick"> + <el-tab-pane v-for="(item, index) in tabList" :key="item.id" :label="item.paramGroupName" + :name="item.paramGroup"> + + <el-form :model="formModels[item.id]" :rules="formRules[item.id]" label-width="120px" + :ref="(el) => (formRefs[index] = el)" style="width: 100%"> + + <el-form-item v-for="(param) in item.paramList" :key="param.id" :label="param.paramName" + :prop="param.paramKey"> + + <el-input v-if="param.paramControlType === 'input'" + v-model="formModels[item.id][param.paramKey]" :placeholder="param.paramPlaceholder" + clearable /> + + <el-upload v-if="param.paramControlType === 'image'" :action="uploadUrl" + list-type="picture-card" :file-list="formModels[item.id][param.paramKey]" + :limit="param.paramLimit" + :on-preview="handlePictureCardPreview" + :on-remove="(file) => handleRemove(file, param)" + :on-success="(response, file, fileList) => handleUploadSuccess(response, file, fileList, param)"> + <i class="el-icon-plus"></i> + </el-upload> + </el-form-item> + + <el-form-item v-if="item.paramList && item.paramList.length > 0"> + <el-button type="primary" @click="submitForm(index)">提交</el-button> + <el-button @click="resetForm(index)">重置</el-button> + </el-form-item> + </el-form> + </el-tab-pane> + </el-tabs> + </el-card> + + <!-- 预览弹窗 --> + <el-dialog :visible.sync="previewVisible"> + <img :src="previewImage" alt="Preview Image" style="width: 100%;" /> + </el-dialog> + </div> +</template> + +<script> + +import utils from 'el-business-utils' + +export default { + data() { + return { + uploadUrl: '', + activeName: 'first', + tabList: [], + previewVisible: false, + previewImage: '', + curTab: {}, + curIndex: 0, + formRefs: [], + formModels: {}, // 存储每个 tab 的 formModel + srcFormModels: {}, // 原始表单数据 + formRules: {}, // 存储每个 tab 的 formRules + }; + }, + + created() { + const config = process.env.config + this.uploadUrl = utils.joinPath(config.httpBaseUri, `flower/api/upload/oss/file`) + }, + async mounted() { + await this.getConfigParamGroup(); + }, + + methods: { + handleClick(tab, event) { + this.chooseTab(tab.index) + }, + + chooseTab(index) { + this.curTab = this.tabList[index]; + this.curIndex = index; + this.getConfigParam(); + }, + + async getConfigParamGroup() { + const { code, data } = await this.$elBusHttp.request('flower/v2/config-param-group/list', { params: {} }); + if (code === 0) { + this.tabList = [...data]; + this.activeName = data[0]?.paramGroup || ''; + this.tabList.forEach(item => { + this.$set(this.formModels, item.id, {}); + this.$set(this.srcFormModels, item.id, {}); // 初始化 srcFormModels + this.$set(this.formRules, item.id, {}); + }); + if (data[0]) { + this.curTab = this.tabList[0]; + this.curIndex = 0; + this.getConfigParam(); + } + + } + }, + + createFormModel(paramList) { + // 创建一个空的对象,用于存储参数 + const model = {}; + paramList.forEach(param => { + // 如果param.paramControlType是image的话,则将值反序列化成ArrayList + if (param.paramControlType === 'image') { + model[param.paramKey] = this.parseFileList(param.paramValue) || []; + } else { + // 默认处理为字符串 + model[param.paramKey] = param.paramValue || ''; + } + }); + return model; + }, + + createFormRules(paramList) { + const rules = {}; + paramList.forEach(param => { + if (param.paramRequire) { + const trigger = param.paramControlType === 'input' ? 'blur' : 'change'; + const rule = [ + { required: true, message: `${param.paramPlaceholder}`, trigger } + ]; + + // 如果param_limit存在且不为null/undefined,添加最大值校验 + if (param.paramLimit) { + // 如果paramControlType是'input',执行最大值校验 + if (param.paramControlType !== 'image') { + rule.push({ + max: param.paramLimit, + message: `${param.paramName}最大值为 ${param.paramLimit}!`, + trigger + }); + } else { + // 如果是image类型,添加自定义验证,判断数组长度 + rule.push({ + validator: (rule, value, callback) => { + if (Array.isArray(value) && value.length > param.paramLimit) { + callback(new Error(`${param.paramName}最多上传 ${param.paramLimit} 张图片`)); + } else { + callback(); // 验证通过 + } + }, + trigger + }); + } + } + + rules[param.paramKey] = rule; + } + }); + return rules; + }, + + async getConfigParam() { + const { code, data } = await this.$elBusHttp.request('flower/v2/config-param/list', { + params: { paramGroupId: this.curTab.id }, + }); + if (code === 0) { + this.tabList[this.curIndex].paramList = [...data]; + + // 构造 formModel 和 formRules,并分别存储到对应的对象中 + const formData = this.createFormModel(data); + this.$set(this.formModels, this.curTab.id, { ...formData }); + this.$set(this.srcFormModels, this.curTab.id, { ...formData }); // 初始化 srcFormModels + this.$set(this.formRules, this.curTab.id, this.createFormRules(data)); + } + }, + + handleRemove(file, param) { + const srcFormModel = this.srcFormModels[this.curTab.id]; + const currentFormModel = this.formModels[this.curTab.id]; + if (file?.response?.code === '0') { + const data = file?.response?.data; + if (data && data[0]) { + const removeFile = data[0] + const updatedFileList = currentFormModel[param.paramKey].filter(item => item.url !== removeFile.url); + // 保存原有的图片控件属性值 + if (updatedFileList.length === 0) { + // 如果文件列表为空,设置为空字符串 + this.$set(currentFormModel, param.paramKey, []); + } else { + // 否则,更新为新的文件列表 JSON 字符串 + this.$set(currentFormModel, param.paramKey, updatedFileList); + + } + + } + + } else if (file && file?.url) { + const updatedFileList = currentFormModel[param.paramKey].filter(item => item.url !== file.url); + // 保存原有的图片控件属性值 + if (updatedFileList.length === 0) { + // 如果文件列表为空,设置为空字符串 + this.$set(currentFormModel, param.paramKey, []); + } else { + // 否则,更新为新的文件列表 JSON 字符串 + this.$set(currentFormModel, param.paramKey, updatedFileList); + + } + } + + }, + + parseFileList(fileListString) { + try { + return JSON.parse(fileListString || '[]'); + } catch (error) { + console.error('Error parsing fileList JSON:', error); + return []; + } + }, + parseFileListCompare(fileListString, groupId, paramKey) { + console.log("parseFileListCompare") + try { + return JSON.parse(fileListString || '[]'); + } catch (error) { + console.error('Error parsing fileList JSON:', error); + return []; + } + + // const newVal = this.formModels[groupId][paramKey] + // const srcVal = this.srcFormModels[groupId][paramKey] + // if (newVal !== srcVal) { + // try { + // return JSON.parse(fileListString || '[]'); + // } catch (error) { + // console.error('Error parsing fileList JSON:', error); + // return []; + // } + // } + }, + + handleUploadSuccess(response, file, fileList, param) { + if (response.code === '0') { + const currentFormModel = this.formModels[this.curTab.id]; + const existingFileList = currentFormModel[param.paramKey]; + const newFile = response.data[0]; + const updatedFileList = [...existingFileList, newFile]; + // this.$set(currentFormModel, param.paramKey, JSON.stringify(updatedFileList)); + currentFormModel[param.paramKey] = updatedFileList; + } else { + this.$message.error('文件上传失败'); + } + }, + + handlePictureCardPreview(file) { + if (file.url) { + this.previewImage = file.url; + this.previewVisible = true; + } else { + this.$message.error('无法预览该文件'); + } + }, + + submitForm(index) { + console.log("submitForm") + console.log(this.formModels[this.curTab.id]) + console.log(this.formRules[this.curTab.id]) + + const formRef = this.formRefs[index]; + if (formRef) { + formRef.validate(async (valid) => { + if (valid) { + + // 这里需要将表单的属性匹配到当前的tabList下的paramList的列 + const tmpParamList = this.tabList[this.curIndex].paramList; + // 遍历 + const submitFormModel = this.formModels[this.curTab.id] + // 遍历 submitFormModel 的属性 + Object.keys(submitFormModel).forEach((key) => { + // 在 tmpParamList 中找到 paramKey 与当前属性 key 匹配的记录 + const paramItem = tmpParamList.find((item) => item.paramKey === key); + if (paramItem) { + // 将 paramValue 设置为表单中对应属性的值 + paramItem.paramValue = submitFormModel[key]; + } + }); + console.log("修改后的值") + console.log(tmpParamList) + const resultArray = tmpParamList + .filter((item) => item.id !== undefined) // 确保 id 存在 + .map((item) => ({ + id: item.id, + paramValue: item.paramControlType === 'image' ? JSON.stringify(item.paramValue) : item.paramValue + })); + + await this.$elBusUtil.confirm('确定要提交吗?') + const { code } = await this.$elBusHttp.request( + 'flower/v2/config-param/update/batch', + { + method: 'put', + data: { + paramList: resultArray, + }, + } + ) + if (code === 0) { + await this.getConfigParam() + this.$message.success('更新成功') + + } + + + // this.$message.success('表单校验成功!'); + // console.log('提交的表单数据: ', this.formModels[this.tabList[index].id]); + } else { + this.$message.error('表单校验失败,请检查填写内容!'); + } + }); + } else { + console.error(`表单引用未找到: formRefs[${index}]`); + } + }, + + resetForm(index) { + // console.log() + // const formRef = this.formRefs[index]; + // if (formRef) { + // formRef.resetFields(); + + // this.$message.info('表单已重置'); + // } else { + // console.error(`未找到表单引用: formRefs[${index}]`); + // } + this.chooseTab(index) + this.activeName = this.tabList[index]?.paramGroup + + }, + }, +}; +</script> diff --git a/services/base.js b/services/base.js index fa007de..8080da9 100644 --- a/services/base.js +++ b/services/base.js @@ -15,6 +15,11 @@ }, getAreaJson(){ return http.request('flower/api/pub/china/area/json') + }, + getBaseInfo(){ + return http.request('flower/v2/config-param/base/info') } + + } } -- Gitblit v1.9.3