1.常规配置:基本配置
2.登录页:图片、公司名称、备案号、公司logo
3.主体页:图片、公司名称、备案号、公司logo
已修改3个文件
已添加1个文件
444 ■■■■■ 文件已修改
layouts/default.vue 46 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/login.vue 54 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/regular/sys.vue 339 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
services/base.js 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
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>
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>
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>
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')
    }
  }
}