Forráskód Böngészése

新增大客户顶部菜单等

hurx 1 napja
szülő
commit
27ddeed1cb

+ 76 - 0
src/api/settings/bottomMenu/index.ts

@@ -0,0 +1,76 @@
+import request from '@/utils/request';
+import { AxiosPromise } from 'axios';
+import { BottomMenuVO, BottomMenuForm, BottomMenuQuery } from '@/api/settings/bottomMenu/types';
+
+/**
+ * 查询大客户底部菜单列表
+ * @param query
+ * @returns {*}
+ */
+
+export const listBottomMenu = (query?: BottomMenuQuery): AxiosPromise<BottomMenuVO[]> => {
+  return request({
+    url: '/system/bottomMenu/list',
+    method: 'get',
+    params: query
+  });
+};
+
+/**
+ * 查询大客户底部菜单详细
+ * @param id
+ */
+export const getBottomMenu = (id: string | number): AxiosPromise<BottomMenuVO> => {
+  return request({
+    url: '/system/bottomMenu/' + id,
+    method: 'get'
+  });
+};
+
+/**
+ * 新增大客户底部菜单
+ * @param data
+ */
+export const addBottomMenu = (data: BottomMenuForm) => {
+  return request({
+    url: '/system/bottomMenu',
+    method: 'post',
+    data: data
+  });
+};
+
+/**
+ * 修改大客户底部菜单
+ * @param data
+ */
+export const updateBottomMenu = (data: BottomMenuForm) => {
+  return request({
+    url: '/system/bottomMenu',
+    method: 'put',
+    data: data
+  });
+};
+
+/**
+ * 删除大客户底部菜单
+ * @param id
+ */
+export const delBottomMenu = (id: string | number | Array<string | number>) => {
+  return request({
+    url: '/system/bottomMenu/' + id,
+    method: 'delete'
+  });
+};
+
+// 修改状态
+export function changeBottomMenuStatus(id: string | number, status: number) {
+  const data = {
+    id,
+    status
+  };
+  return request({
+    url: '/system/bottomMenu/changeStatus',
+    method: 'put',
+    data: data
+  });
+}

+ 125 - 0
src/api/settings/bottomMenu/types.ts

@@ -0,0 +1,125 @@
+export interface BottomMenuVO {
+  /**
+   *
+   */
+  id: string | number;
+
+  /**
+   *
+   */
+  parentId: string | number;
+
+  /**
+   *
+   */
+  name: string;
+
+  /**
+   *
+   */
+  link: string;
+
+  /**
+   *
+   */
+  sort: number;
+
+  /**
+   *
+   */
+  status: number;
+
+  /**
+   *
+   */
+  target: string;
+
+  /**
+   * 备注
+   */
+  remark: string;
+}
+
+export interface BottomMenuForm extends BaseEntity {
+  /**
+   *
+   */
+  id?: string | number;
+
+  /**
+   *
+   */
+  parentId?: string | number;
+
+  /**
+   *
+   */
+  name?: string;
+
+  /**
+   *
+   */
+  link?: string;
+
+  /**
+   *
+   */
+  sort?: number;
+
+  /**
+   *
+   */
+  status?: number;
+
+  /**
+   *
+   */
+  target?: string;
+
+  /**
+   * 备注
+   */
+  remark?: string;
+}
+
+export interface BottomMenuQuery extends PageQuery {
+  /**
+   *
+   */
+  parentId?: string | number;
+
+  /**
+   *
+   */
+  name?: string;
+
+  /**
+   *
+   */
+  link?: string;
+
+  /**
+   *
+   */
+  sort?: number;
+
+  /**
+   *
+   */
+  status?: number;
+
+  /**
+   *
+   */
+  target?: string;
+
+  /**
+   * 平台标识
+   */
+  platformCode?: string;
+
+  /**
+   * 日期范围参数
+   */
+  params?: any;
+}

+ 73 - 0
src/api/settings/copyrightInfo/index.ts

@@ -0,0 +1,73 @@
+import request from '@/utils/request';
+import { AxiosPromise } from 'axios';
+import { CopyrightInfoVO, CopyrightInfoForm, CopyrightInfoQuery } from '@/api/settings/copyrightInfo/types';
+
+/**
+ * 查询大客户版权信息列表
+ * @param query
+ * @returns {*}
+ */
+
+export const listCopyrightInfo = (query?: CopyrightInfoQuery): AxiosPromise<CopyrightInfoVO[]> => {
+  return request({
+    url: '/system/copyrightInfo/list',
+    method: 'get',
+    params: query
+  });
+};
+
+/**
+ * 查询大客户版权信息详细
+ * @param id
+ */
+export const getCopyrightInfo = (id: string | number): AxiosPromise<CopyrightInfoVO> => {
+  return request({
+    url: '/system/copyrightInfo/' + id,
+    method: 'get'
+  });
+};
+
+/**
+ * 新增大客户版权信息
+ * @param data
+ */
+export const addCopyrightInfo = (data: CopyrightInfoForm) => {
+  return request({
+    url: '/system/copyrightInfo',
+    method: 'post',
+    data: data
+  });
+};
+
+/**
+ * 修改大客户版权信息
+ * @param data
+ */
+export const updateCopyrightInfo = (data: CopyrightInfoForm) => {
+  return request({
+    url: '/system/copyrightInfo',
+    method: 'put',
+    data: data
+  });
+};
+
+/**
+ * 删除大客户版权信息
+ * @param id
+ */
+export const delCopyrightInfo = (id: string | number | Array<string | number>) => {
+  return request({
+    url: '/system/copyrightInfo/' + id,
+    method: 'delete'
+  });
+};
+
+/**
+ * 获取当前配置
+ */
+export const getCurrentCopyrightInfo = () => {
+  return request({
+    url: '/system/copyrightInfo/current',
+    method: 'get'
+  });
+};

+ 200 - 0
src/api/settings/copyrightInfo/types.ts

@@ -0,0 +1,200 @@
+export interface CopyrightInfoVO {
+  /**
+   *
+   */
+  id: string | number;
+
+  /**
+   * 版权所有
+   */
+  owner: string;
+
+  /**
+   * 备案号
+   */
+  icp: string;
+
+  /**
+   * 公安备案
+   */
+  police: string;
+
+  /**
+   * 联系电话
+   */
+  phone: string;
+
+  /**
+   * 客服电话
+   */
+  customerPhone: string;
+
+  /**
+   * 客服二维码
+   */
+  customerQr: string;
+
+  /**
+   * 底部Logo
+   */
+  logo: string;
+
+  /**
+   * 公众号名称
+   */
+  wechatTitle: string;
+
+  /**
+   * 公众号二维码
+   */
+  wechatQr: string;
+
+  /**
+   * 微博名称
+   */
+  weiboTitle: string;
+
+  /**
+   * 微博二维码
+   */
+  weiboQr: string;
+
+  /**
+   * 备注
+   */
+  remark: string;
+}
+
+export interface CopyrightInfoForm extends BaseEntity {
+  /**
+   *
+   */
+  id?: string | number;
+
+  /**
+   * 版权所有
+   */
+  owner?: string;
+
+  /**
+   * 备案号
+   */
+  icp?: string;
+
+  /**
+   * 公安备案
+   */
+  police?: string;
+
+  /**
+   * 联系电话
+   */
+  phone?: string;
+
+  /**
+   * 客服电话
+   */
+  customerPhone?: string;
+
+  /**
+   * 客服二维码
+   */
+  customerQr?: string;
+
+  /**
+   * 底部Logo
+   */
+  logo?: string;
+
+  /**
+   * 公众号名称
+   */
+  wechatTitle?: string;
+
+  /**
+   * 公众号二维码
+   */
+  wechatQr?: string;
+
+  /**
+   * 微博名称
+   */
+  weiboTitle?: string;
+
+  /**
+   * 微博二维码
+   */
+  weiboQr?: string;
+
+  /**
+   * 备注
+   */
+  remark?: string;
+}
+
+export interface CopyrightInfoQuery extends PageQuery {
+  /**
+   * 版权所有
+   */
+  owner?: string;
+
+  /**
+   * 备案号
+   */
+  icp?: string;
+
+  /**
+   * 公安备案
+   */
+  police?: string;
+
+  /**
+   * 联系电话
+   */
+  phone?: string;
+
+  /**
+   * 客服电话
+   */
+  customerPhone?: string;
+
+  /**
+   * 客服二维码
+   */
+  customerQr?: string;
+
+  /**
+   * 底部Logo
+   */
+  logo?: string;
+
+  /**
+   * 公众号名称
+   */
+  wechatTitle?: string;
+
+  /**
+   * 公众号二维码
+   */
+  wechatQr?: string;
+
+  /**
+   * 微博名称
+   */
+  weiboTitle?: string;
+
+  /**
+   * 微博二维码
+   */
+  weiboQr?: string;
+
+  /**
+   * 平台标识
+   */
+  platformCode?: string;
+
+  /**
+   * 日期范围参数
+   */
+  params?: any;
+}

+ 73 - 0
src/api/settings/mobileHuicaiConfig/index.ts

@@ -0,0 +1,73 @@
+import request from '@/utils/request';
+import { AxiosPromise } from 'axios';
+import { MobileHuicaiConfigVO, MobileHuicaiConfigForm, MobileHuicaiConfigQuery } from '@/api/settings/mobileHuicaiConfig/types';
+
+/**
+ * 查询大客户手机慧采配置列表
+ * @param query
+ * @returns {*}
+ */
+
+export const listMobileHuicaiConfig = (query?: MobileHuicaiConfigQuery): AxiosPromise<MobileHuicaiConfigVO[]> => {
+  return request({
+    url: '/system/mobileHuicaiConfig/list',
+    method: 'get',
+    params: query
+  });
+};
+
+/**
+ * 查询大客户手机慧采配置详细
+ * @param id
+ */
+export const getMobileHuicaiConfig = (id: string | number): AxiosPromise<MobileHuicaiConfigVO> => {
+  return request({
+    url: '/system/mobileHuicaiConfig/' + id,
+    method: 'get'
+  });
+};
+
+/**
+ * 新增大客户手机慧采配置
+ * @param data
+ */
+export const addMobileHuicaiConfig = (data: MobileHuicaiConfigForm) => {
+  return request({
+    url: '/system/mobileHuicaiConfig',
+    method: 'post',
+    data: data
+  });
+};
+
+/**
+ * 修改大客户手机慧采配置
+ * @param data
+ */
+export const updateMobileHuicaiConfig = (data: MobileHuicaiConfigForm) => {
+  return request({
+    url: '/system/mobileHuicaiConfig',
+    method: 'put',
+    data: data
+  });
+};
+
+/**
+ * 删除大客户手机慧采配置
+ * @param id
+ */
+export const delMobileHuicaiConfig = (id: string | number | Array<string | number>) => {
+  return request({
+    url: '/system/mobileHuicaiConfig/' + id,
+    method: 'delete'
+  });
+};
+
+/**
+ * 获取当前配置
+ */
+export const getCurrentMobileHuicaiConfig = () => {
+  return request({
+    url: '/system/mobileHuicaiConfig/current',
+    method: 'get'
+  });
+};

+ 140 - 0
src/api/settings/mobileHuicaiConfig/types.ts

@@ -0,0 +1,140 @@
+export interface MobileHuicaiConfigVO {
+  /**
+   *
+   */
+  id: string | number;
+
+  /**
+   *
+   */
+  menuName: string;
+
+  /**
+   *
+   */
+  miniProgramTitle: string;
+
+  /**
+   *
+   */
+  miniProgramSubTitle: string;
+
+  /**
+   *
+   */
+  miniProgramQr: string;
+
+  /**
+   *
+   */
+  wechatServiceTitle: string;
+
+  /**
+   *
+   */
+  wechatServiceSubTitle: string;
+
+  /**
+   *
+   */
+  wechatServiceQr: string;
+
+  /**
+   * 备注
+   */
+  remark: string;
+}
+
+export interface MobileHuicaiConfigForm extends BaseEntity {
+  /**
+   *
+   */
+  id?: string | number;
+
+  /**
+   *
+   */
+  menuName?: string;
+
+  /**
+   *
+   */
+  miniProgramTitle?: string;
+
+  /**
+   *
+   */
+  miniProgramSubTitle?: string;
+
+  /**
+   *
+   */
+  miniProgramQr?: string;
+
+  /**
+   *
+   */
+  wechatServiceTitle?: string;
+
+  /**
+   *
+   */
+  wechatServiceSubTitle?: string;
+
+  /**
+   *
+   */
+  wechatServiceQr?: string;
+
+  /**
+   * 备注
+   */
+  remark?: string;
+}
+
+export interface MobileHuicaiConfigQuery extends PageQuery {
+  /**
+   *
+   */
+  menuName?: string;
+
+  /**
+   *
+   */
+  miniProgramTitle?: string;
+
+  /**
+   *
+   */
+  miniProgramSubTitle?: string;
+
+  /**
+   *
+   */
+  miniProgramQr?: string;
+
+  /**
+   *
+   */
+  wechatServiceTitle?: string;
+
+  /**
+   *
+   */
+  wechatServiceSubTitle?: string;
+
+  /**
+   *
+   */
+  wechatServiceQr?: string;
+
+  /**
+   * 平台标识
+   */
+  platformCode?: string;
+
+  /**
+   * 日期范围参数
+   */
+  params?: any;
+}

+ 76 - 0
src/api/settings/topMenu/index.ts

@@ -0,0 +1,76 @@
+import request from '@/utils/request';
+import { AxiosPromise } from 'axios';
+import { TopMenuVO, TopMenuForm, TopMenuQuery } from '@/api/settings/topMenu/types';
+
+/**
+ * 查询大客户顶部菜单列表
+ * @param query
+ * @returns {*}
+ */
+
+export const listTopMenu = (query?: TopMenuQuery): AxiosPromise<TopMenuVO[]> => {
+  return request({
+    url: '/system/topMenu/list',
+    method: 'get',
+    params: query
+  });
+};
+
+/**
+ * 查询大客户顶部菜单详细
+ * @param id
+ */
+export const getTopMenu = (id: string | number): AxiosPromise<TopMenuVO> => {
+  return request({
+    url: '/system/topMenu/' + id,
+    method: 'get'
+  });
+};
+
+/**
+ * 新增大客户顶部菜单
+ * @param data
+ */
+export const addTopMenu = (data: TopMenuForm) => {
+  return request({
+    url: '/system/topMenu',
+    method: 'post',
+    data: data
+  });
+};
+
+/**
+ * 修改大客户顶部菜单
+ * @param data
+ */
+export const updateTopMenu = (data: TopMenuForm) => {
+  return request({
+    url: '/system/topMenu',
+    method: 'put',
+    data: data
+  });
+};
+
+/**
+ * 删除大客户顶部菜单
+ * @param id
+ */
+export const delTopMenu = (id: string | number | Array<string | number>) => {
+  return request({
+    url: '/system/topMenu/' + id,
+    method: 'delete'
+  });
+};
+
+// 修改状态
+export function changeTopMenuStatus(id: string | number, status: number) {
+  const data = {
+    id,
+    status
+  };
+  return request({
+    url: '/system/topMenu/changeStatus',
+    method: 'put',
+    data: data
+  });
+}

+ 125 - 0
src/api/settings/topMenu/types.ts

@@ -0,0 +1,125 @@
+export interface TopMenuVO {
+  /**
+   *
+   */
+  id: string | number;
+
+  /**
+   *
+   */
+  parentId: string | number;
+
+  /**
+   *
+   */
+  name: string;
+
+  /**
+   *
+   */
+  link: string;
+
+  /**
+   *
+   */
+  sort: number;
+
+  /**
+   *
+   */
+  status: number;
+
+  /**
+   *
+   */
+  target: string;
+
+  /**
+   * 备注
+   */
+  remark: string;
+}
+
+export interface TopMenuForm extends BaseEntity {
+  /**
+   *
+   */
+  id?: string | number;
+
+  /**
+   *
+   */
+  parentId?: string | number;
+
+  /**
+   *
+   */
+  name?: string;
+
+  /**
+   *
+   */
+  link?: string;
+
+  /**
+   *
+   */
+  sort?: number;
+
+  /**
+   *
+   */
+  status?: number;
+
+  /**
+   *
+   */
+  target?: string;
+
+  /**
+   * 备注
+   */
+  remark?: string;
+}
+
+export interface TopMenuQuery extends PageQuery {
+  /**
+   *
+   */
+  parentId?: string | number;
+
+  /**
+   *
+   */
+  name?: string;
+
+  /**
+   *
+   */
+  link?: string;
+
+  /**
+   *
+   */
+  sort?: number;
+
+  /**
+   *
+   */
+  status?: number;
+
+  /**
+   *
+   */
+  target?: string;
+
+  /**
+   * 平台标识
+   */
+  platformCode?: string;
+
+  /**
+   * 日期范围参数
+   */
+  params?: any;
+}

+ 3 - 3
src/views/platform/operation/announcement/index.vue

@@ -29,9 +29,9 @@
           <el-table-column label="封面图片" align="center" width="100">
             <template #default="scope">
               <el-image
-                v-if="scope.row.coverImageUrl"
-                :src="scope.row.coverImageUrl"
-                :preview-src-list="[scope.row.coverImageUrl]"
+                v-if="scope.row.coverImage"
+                :src="scope.row.coverImage"
+                :preview-src-list="[scope.row.coverImage]"
                 fit="contain"
                 style="width: 60px; height: 60px"
                 preview-teleported

+ 807 - 0
src/views/settings/MenuSettings.vue

@@ -0,0 +1,807 @@
+<template>
+  <div class="menu-settings-container">
+    <el-tabs v-model="activeTab" class="custom-tabs">
+      <!-- 顶部菜单 (树形二级结构) -->
+      <el-tab-pane label="顶部菜单" name="top">
+        <div class="tab-content">
+          <div class="action-bar">
+            <el-button type="primary" icon="Plus" @click="handleAdd('top')" class="btn-primary-blue">新增顶部一级菜单</el-button>
+          </div>
+
+          <el-table
+            :data="topMenuList"
+            border
+            style="width: 100%"
+            header-cell-class-name="table-header-custom"
+            class="standard-table"
+            row-key="id"
+            default-expand-all
+          >
+            <el-table-column label="序号" type="index" width="70" align="center" />
+            <el-table-column prop="name" label="菜单名称" min-width="200" />
+            <el-table-column prop="sort" label="排序" width="100" align="center" sortable />
+            <el-table-column prop="link" label="跳转地址" min-width="250" show-overflow-tooltip />
+            <el-table-column label="状态" width="100" align="center">
+              <template #default="{ row }">
+                <el-switch
+                  v-model="row.status"
+                  :active-value="1"
+                  :inactive-value="0"
+                  active-color="#1890ff"
+                  @change="changeTopMenuStatus(row.id, row.status)"
+                />
+              </template>
+            </el-table-column>
+            <el-table-column label="操作" width="220" align="center">
+              <template #default="scope">
+                <el-button v-if="!scope.row.parentId" link type="primary" class="text-blue" @click="handleAddSubTop(scope.row)">添加子菜单</el-button>
+                <el-button link type="primary" class="text-blue" @click="handleEdit('top', scope.row, scope.$index)">编辑</el-button>
+                <el-button link type="danger" @click="handleDelete('top', scope.$index, scope.row)">删除</el-button>
+              </template>
+            </el-table-column>
+          </el-table>
+        </div>
+      </el-tab-pane>
+
+      <!-- 底部菜单 (保持树形二级结构) -->
+      <el-tab-pane label="底部菜单" name="bottom">
+        <div class="tab-content">
+          <div class="action-bar">
+            <el-button type="primary" icon="Plus" @click="handleAdd('bottom')" class="btn-primary-blue">新增底部一级菜单</el-button>
+          </div>
+          <el-table
+            :data="bottomMenuList"
+            border
+            style="width: 100%"
+            header-cell-class-name="table-header-custom"
+            class="standard-table"
+            row-key="id"
+            default-expand-all
+          >
+            <el-table-column label="序号" type="index" width="70" align="center" />
+            <el-table-column prop="name" label="菜单名称" min-width="200" />
+            <el-table-column prop="sort" label="排序" width="100" align="center" sortable />
+            <el-table-column prop="link" label="跳转地址" min-width="250" show-overflow-tooltip />
+            <el-table-column label="状态" width="100" align="center">
+              <template #default="{ row }">
+                <el-switch
+                  v-model="row.status"
+                  :active-value="1"
+                  :inactive-value="0"
+                  active-color="#1890ff"
+                  @change="changeBottomMenuStatus(row.id, row.status)"
+                />
+              </template>
+            </el-table-column>
+            <el-table-column label="操作" width="220" align="center">
+              <template #default="scope">
+                <el-button v-if="!scope.row.parentId" link type="primary" class="text-blue" @click="handleAddSub(scope.row)">添加子菜单</el-button>
+                <el-button link type="primary" class="text-blue" @click="handleEdit('bottom', scope.row, scope.$index)">编辑</el-button>
+                <el-button link type="danger" @click="handleDelete('bottom', scope.$index, scope.row)">删除</el-button>
+              </template>
+            </el-table-column>
+          </el-table>
+        </div>
+      </el-tab-pane>
+
+      <!-- 手机慧采 -->
+      <el-tab-pane label="手机慧采" name="phone">
+        <div class="tab-content">
+          <div class="copyright-container">
+            <el-form :model="phoneForm" label-width="120px" class="copyright-form">
+              <div class="form-section">
+                <div class="section-title">基本信息</div>
+                <div class="grid-form-fields">
+                  <el-form-item label="菜单名称:">
+                    <el-input v-model="phoneForm.menuName" placeholder="如:手机慧采" />
+                  </el-form-item>
+                </div>
+              </div>
+
+              <div class="form-section">
+                <div class="section-title">移动资产矩阵</div>
+                <div class="social-config-row">
+                  <!-- 小程序配置 -->
+                  <div class="social-item">
+                    <div class="social-label">小程序端配置</div>
+                    <el-form-item label="主标题:" label-width="80px">
+                      <el-input v-model="phoneForm.miniProgramTitle" placeholder="如:体验小程序" />
+                    </el-form-item>
+                    <el-form-item label="副标题:" label-width="80px">
+                      <el-input v-model="phoneForm.miniProgramSubTitle" placeholder="如:随时随地 快捷采购" />
+                    </el-form-item>
+                    <el-form-item label="二维码:" label-width="80px">
+                      <UploadImage v-model="phoneForm.miniProgramQR" :limit="1" />
+                      <div class="field-tip" style="margin-top: 0">上传小程序太阳码</div>
+                    </el-form-item>
+                  </div>
+
+                  <!-- 微信公众号服务配置 -->
+                  <div class="social-item">
+                    <div class="social-label">微信服务号配置</div>
+                    <el-form-item label="主标题:" label-width="80px">
+                      <el-input v-model="phoneForm.wechatServiceTitle" placeholder="如:关注公众号" />
+                    </el-form-item>
+                    <el-form-item label="副标题:" label-width="80px">
+                      <el-input v-model="phoneForm.wechatServiceSubTitle" placeholder="如:获取最新折扣与会员权益" />
+                    </el-form-item>
+                    <el-form-item label="二维码:" label-width="80px">
+                      <UploadImage v-model="phoneForm.wechatServiceQR" :limit="1" />
+                      <div class="field-tip" style="margin-top: 0">上传微信公众号服务二维码</div>
+                    </el-form-item>
+                  </div>
+                </div>
+              </div>
+
+              <div class="form-footer">
+                <el-button type="primary" @click="savePhoneSettings" class="btn-primary-blue" size="large">保存手机页配置</el-button>
+              </div>
+            </el-form>
+          </div>
+        </div>
+      </el-tab-pane>
+
+      <!-- 版权信息 -->
+      <el-tab-pane label="版权信息" name="copyright">
+        <div class="tab-content">
+          <div class="copyright-container">
+            <el-form :model="copyrightForm" label-width="120px" class="copyright-form">
+              <!-- 基本信息 (一排放2个字段,网格化重构) -->
+              <div class="form-section">
+                <div class="section-title">基本信息</div>
+                <div class="grid-form-fields">
+                  <el-form-item label="版权所有:">
+                    <el-input v-model="copyrightForm.owner" placeholder="如:© 2024 优易企业购 版权所有" />
+                  </el-form-item>
+                  <el-form-item label="备案号:">
+                    <el-input v-model="copyrightForm.icp" placeholder="如:苏ICP备12345678号" />
+                  </el-form-item>
+                  <el-form-item label="公安备案:">
+                    <el-input v-model="copyrightForm.police" placeholder="如:苏公网安备 1234567890号" />
+                  </el-form-item>
+                  <el-form-item label="联系电话:">
+                    <el-input v-model="copyrightForm.phone" placeholder="如:400-123-4567" />
+                  </el-form-item>
+                  <el-form-item label="客服电话:">
+                    <el-input v-model="copyrightForm.customerPhone" placeholder="如:400-666-8888" />
+                  </el-form-item>
+                  <el-form-item label="客服二维码:">
+                    <UploadImage v-model="copyrightForm.customerQR" :limit="1" />
+                    <div class="field-tip" style="margin-top: 0">上传客服微信二维码,支持用户扫码添加专属客服</div>
+                  </el-form-item>
+                </div>
+              </div>
+
+              <!-- 品牌资产 (一排放2个字段,Logo与上传对齐) -->
+              <div class="form-section">
+                <div class="section-title">品牌资产</div>
+                <div class="grid-form-fields" style="align-items: center">
+                  <el-form-item label="底部Logo:">
+                    <UploadImage v-model="copyrightForm.logo" :limit="1" />
+                  </el-form-item>
+                  <div class="field-tip" style="margin-top: 0; padding-left: 20px">
+                    建议尺寸:160 * 78,格式:PNG/SVG。大白底或透明背景,完美契合页脚视觉资产
+                  </div>
+                </div>
+              </div>
+
+              <!-- 社交媒体 (二维码不要换行显示调大至 80px) -->
+              <div class="form-section">
+                <div class="section-title">社交媒体</div>
+                <div class="social-config-row">
+                  <div class="social-item">
+                    <div class="social-label">公众号配置</div>
+                    <el-form-item label="名称:" label-width="80px">
+                      <el-input v-model="copyrightForm.wechatTitle" placeholder="如:关注公众号" />
+                    </el-form-item>
+                    <el-form-item label="二维码:" label-width="80px">
+                      <UploadImage v-model="copyrightForm.wechatQR" :limit="1" />
+                    </el-form-item>
+                  </div>
+
+                  <div class="social-item">
+                    <div class="social-label">微博配置</div>
+                    <el-form-item label="名称:" label-width="80px">
+                      <el-input v-model="copyrightForm.weiboTitle" placeholder="如:关注微博" />
+                    </el-form-item>
+                    <el-form-item label="二维码:" label-width="80px">
+                      <UploadImage v-model="copyrightForm.weiboQR" :limit="1" />
+                    </el-form-item>
+                  </div>
+                </div>
+              </div>
+
+              <div class="form-footer">
+                <el-button type="primary" @click="saveCopyright" class="btn-primary-blue" size="large">保存版权页配置</el-button>
+              </div>
+            </el-form>
+          </div>
+        </div>
+      </el-tab-pane>
+    </el-tabs>
+
+    <!-- 编辑弹窗 -->
+    <el-dialog v-model="dialogVisible" :title="dialogType === 'add' ? '新增菜单' : '编辑菜单'" width="550px" class="custom-dialog">
+      <el-form :model="menuForm" label-width="100px" class="p-t-10">
+        <el-form-item label="上级菜单:">
+          <el-select v-model="menuForm.parentId" placeholder="请选择上级菜单" clearable style="width: 100%">
+            <el-option label="无 (作为一级菜单)" :value="null" />
+            <el-option
+              v-for="item in currentMenuType === 'top' ? topMenuList : bottomMenuList"
+              :key="item.id"
+              :label="item.name"
+              :value="item.id"
+              :disabled="item.id === menuForm.id"
+            />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="菜单名称:">
+          <el-input v-model="menuForm.name" placeholder="请输入菜单名称" />
+        </el-form-item>
+        <el-form-item label="跳转地址:">
+          <WebLinkInput v-model="menuForm.link" placeholder="请输入链接或点击选择" />
+        </el-form-item>
+        <el-form-item label="菜单排序:">
+          <el-input-number v-model="menuForm.sort" :min="1" placeholder="数字越小越靠前" style="width: 100%" />
+        </el-form-item>
+        <el-form-item label="启用状态:">
+          <el-switch v-model="menuForm.status" :active-value="1" :inactive-value="0" active-color="#1890ff" />
+        </el-form-item>
+      </el-form>
+      <template #footer>
+        <el-button @click="dialogVisible = false">取消</el-button>
+        <el-button type="primary" @click="confirmSubmit" class="btn-primary-blue">确定</el-button>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+
+<script lang="ts" setup>
+import { ref, reactive, onMounted } from 'vue';
+import { ElMessage, ElMessageBox } from 'element-plus';
+import { globalHeaders } from '@/utils/request';
+import { listTopMenu, addTopMenu, updateTopMenu, delTopMenu, changeTopMenuStatus } from '@/api/settings/topMenu';
+import { addMobileHuicaiConfig, updateMobileHuicaiConfig, getCurrentMobileHuicaiConfig } from '@/api/settings/mobileHuicaiConfig';
+import { addCopyrightInfo, updateCopyrightInfo, getCurrentCopyrightInfo } from '@/api/settings/copyrightInfo';
+import { listBottomMenu, addBottomMenu, updateBottomMenu, delBottomMenu, changeBottomMenuStatus } from '@/api/settings/bottomMenu';
+
+const activeTab = ref('top');
+
+const uploadUrl = ref(import.meta.env.VITE_APP_BASE_API + '/resource/oss/upload');
+const uploadHeaders = ref(globalHeaders());
+
+const beforeCellUpload = (file: any) => {
+  const isImg = file.type.indexOf('image') > -1;
+  if (!isImg) {
+    ElMessage.error('只能上传图片文件');
+    return false;
+  }
+  const isLt5M = file.size / 1024 / 1024 < 5;
+  if (!isLt5M) {
+    ElMessage.error('图片大小不能超过 5MB');
+    return false;
+  }
+  return true;
+};
+
+// === 顶部菜单 ===
+const topMenuList = ref<any[]>([]);
+
+const buildTree = (list: any[]) => {
+  const tree: any[] = [];
+  const map = new Map<string, any>();
+  list.forEach((item) => {
+    map.set(String(item.id), { ...item, children: [] });
+  });
+  map.forEach((item) => {
+    if (item.parentId && map.has(String(item.parentId))) {
+      map.get(String(item.parentId))!.children.push(item);
+    } else {
+      tree.push(item);
+    }
+  });
+  const cleanEmpties = (nodes: any[]) => {
+    nodes.forEach((n) => {
+      if (n.children && n.children.length === 0) delete n.children;
+      else if (n.children) cleanEmpties(n.children);
+    });
+  };
+  cleanEmpties(tree);
+  return tree;
+};
+
+const loadTopMenus = async () => {
+  try {
+    const res = await listTopMenu({ pageNum: 1, pageSize: 500 } as any);
+    topMenuList.value = buildTree(res.rows || []);
+  } catch (error) {
+    console.error('加载顶部菜单失败', error);
+  }
+};
+
+const loadBottomMenus = async () => {
+  try {
+    const res = await listBottomMenu({ pageNum: 1, pageSize: 500 } as any);
+    bottomMenuList.value = buildTree(res.rows || []);
+  } catch (error) {
+    console.error('加载底部菜单失败', error);
+  }
+};
+
+// === 底部菜单 ===
+const bottomMenuList = ref<any[]>([]);
+
+// === 手机慧采 ===
+const phoneConfigId = ref<number | string>('');
+const phoneForm = reactive({
+  menuName: '手机慧采',
+  miniProgramQR: '',
+  miniProgramTitle: '体验小程序',
+  miniProgramSubTitle: '随时随地 快捷采购',
+  wechatServiceQR: '',
+  wechatServiceTitle: '关注公众号',
+  wechatServiceSubTitle: '获取最新折扣与会员权益'
+});
+
+const loadPhoneConfig = async () => {
+  try {
+    const res = (await getCurrentMobileHuicaiConfig()) as any;
+    if (res.data) {
+      const d = res.data;
+      phoneConfigId.value = d.id || '';
+      phoneForm.menuName = d.menuName || '手机慧采';
+      phoneForm.miniProgramQR = d.miniProgramQr || '';
+      phoneForm.miniProgramTitle = d.miniProgramTitle || '体验小程序';
+      phoneForm.miniProgramSubTitle = d.miniProgramSubTitle || '随时随地 快捷采购';
+      phoneForm.wechatServiceQR = d.wechatServiceQr || '';
+      phoneForm.wechatServiceTitle = d.wechatServiceTitle || '关注公众号';
+      phoneForm.wechatServiceSubTitle = d.wechatServiceSubTitle || '获取最新折扣与会员权益';
+    }
+  } catch (error) {
+    console.error('加载手机慧采配置失败', error);
+  }
+};
+
+const savePhoneSettings = async () => {
+  try {
+    const data: any = {
+      menuName: phoneForm.menuName,
+      miniProgramTitle: phoneForm.miniProgramTitle,
+      miniProgramSubTitle: phoneForm.miniProgramSubTitle,
+      miniProgramQr: phoneForm.miniProgramQR,
+      wechatServiceTitle: phoneForm.wechatServiceTitle,
+      wechatServiceSubTitle: phoneForm.wechatServiceSubTitle,
+      wechatServiceQr: phoneForm.wechatServiceQR
+    };
+    if (phoneConfigId.value) {
+      data.id = phoneConfigId.value;
+      await updateMobileHuicaiConfig(data);
+    } else {
+      const res = (await addMobileHuicaiConfig(data)) as any;
+      if (res.data?.id) phoneConfigId.value = res.data.id;
+    }
+    ElMessage.success('手机页配置保存成功');
+  } catch (error) {
+    ElMessage.error('保存失败');
+  }
+};
+
+// === 版权信息 ===
+const copyrightConfigId = ref<number | string>('');
+const copyrightForm = reactive({
+  owner: '© 2024 优易企业购 版权所有',
+  icp: '苏ICP备12345678号',
+  police: '苏公网安备 1234567890号',
+  phone: '400-123-4567',
+  customerPhone: '400-666-8888',
+  customerQR: '',
+  logo: '',
+  wechatTitle: '关注公众号',
+  wechatQR: '',
+  weiboTitle: '关注微博',
+  weiboQR: ''
+});
+
+const loadCopyright = async () => {
+  try {
+    const res = (await getCurrentCopyrightInfo()) as any;
+    if (res.data) {
+      const d = res.data;
+      copyrightConfigId.value = d.id || '';
+      copyrightForm.owner = d.owner || '';
+      copyrightForm.icp = d.icp || '';
+      copyrightForm.police = d.police || '';
+      copyrightForm.phone = d.phone || '';
+      copyrightForm.customerPhone = d.customerPhone || '';
+      copyrightForm.customerQR = d.customerQr || '';
+      copyrightForm.logo = d.logo || '';
+      copyrightForm.wechatTitle = d.wechatTitle || '';
+      copyrightForm.wechatQR = d.wechatQr || '';
+      copyrightForm.weiboTitle = d.weiboTitle || '';
+      copyrightForm.weiboQR = d.weiboQr || '';
+    }
+  } catch (error) {
+    console.error('加载版权信息失败', error);
+  }
+};
+
+const saveCopyright = async () => {
+  try {
+    const data: any = {
+      owner: copyrightForm.owner,
+      icp: copyrightForm.icp,
+      police: copyrightForm.police,
+      phone: copyrightForm.phone,
+      customerPhone: copyrightForm.customerPhone,
+      customerQr: copyrightForm.customerQR,
+      logo: copyrightForm.logo,
+      wechatTitle: copyrightForm.wechatTitle,
+      wechatQr: copyrightForm.wechatQR,
+      weiboTitle: copyrightForm.weiboTitle,
+      weiboQr: copyrightForm.weiboQR
+    };
+    if (copyrightConfigId.value) {
+      data.id = copyrightConfigId.value;
+      await updateCopyrightInfo(data);
+    } else {
+      const res = (await addCopyrightInfo(data)) as any;
+      if (res.data?.id) copyrightConfigId.value = res.data.id;
+    }
+    ElMessage.success('版权信息保存成功');
+  } catch (error) {
+    ElMessage.error('保存失败');
+  }
+};
+
+// === 弹窗逻辑 ===
+const dialogVisible = ref(false);
+const dialogType = ref('add');
+const currentMenuType = ref('top');
+const menuForm = reactive({
+  id: null as number | string | null,
+  name: '',
+  link: '',
+  target: '_self',
+  status: 1,
+  sort: 100,
+  parentId: null as number | string | null
+});
+
+const handleAdd = (type: string) => {
+  currentMenuType.value = type;
+  dialogType.value = 'add';
+  Object.assign(menuForm, { id: null, name: '', link: '', target: '_self', status: 1, sort: 100, parentId: null });
+  dialogVisible.value = true;
+};
+
+const handleAddSub = (parentRow: any) => {
+  currentMenuType.value = 'bottom';
+  dialogType.value = 'add';
+  Object.assign(menuForm, { id: null, name: '', link: '', target: '_self', status: 1, sort: 100, parentId: parentRow.id });
+  dialogVisible.value = true;
+};
+
+const handleAddSubTop = (parentRow: any) => {
+  currentMenuType.value = 'top';
+  dialogType.value = 'add';
+  Object.assign(menuForm, { id: null, name: '', link: '', target: '_self', status: 1, sort: 100, parentId: parentRow.id });
+  dialogVisible.value = true;
+};
+
+const handleEdit = (type: string, row: any, _index: number) => {
+  currentMenuType.value = type;
+  dialogType.value = 'edit';
+  Object.assign(menuForm, JSON.parse(JSON.stringify(row)));
+  dialogVisible.value = true;
+};
+
+const confirmSubmit = async () => {
+  if (!menuForm.name) return ElMessage.warning('请输入菜单名称');
+
+  try {
+    const data: any = {
+      name: menuForm.name,
+      link: menuForm.link,
+      target: menuForm.target,
+      status: menuForm.status,
+      sort: menuForm.sort,
+      parentId: menuForm.parentId || undefined
+    };
+
+    if (currentMenuType.value === 'top') {
+      if (menuForm.id) {
+        data.id = menuForm.id;
+        await updateTopMenu(data);
+      } else {
+        await addTopMenu(data);
+      }
+      await loadTopMenus();
+    } else {
+      if (menuForm.id) {
+        data.id = menuForm.id;
+        await updateBottomMenu(data);
+      } else {
+        await addBottomMenu(data);
+      }
+      await loadBottomMenus();
+    }
+    ElMessage.success(dialogType.value === 'add' ? '新增成功' : '修改成功');
+    dialogVisible.value = false;
+  } catch (error) {
+    ElMessage.error('保存失败');
+  }
+};
+
+const handleDelete = (type: string, _index: number, row: any) => {
+  ElMessageBox.confirm('确定要删除该菜单吗?', '提示', { type: 'warning' }).then(async () => {
+    try {
+      if (type === 'top') {
+        await delTopMenu(row.id);
+        await loadTopMenus();
+      } else {
+        await delBottomMenu(row.id);
+        await loadBottomMenus();
+      }
+      ElMessage.success('删除成功');
+    } catch (error) {
+      ElMessage.error('删除失败');
+    }
+  });
+};
+
+onMounted(() => {
+  loadTopMenus();
+  loadBottomMenus();
+  loadPhoneConfig();
+  loadCopyright();
+});
+</script>
+
+<style scoped>
+.menu-settings-container {
+  padding: 30px;
+  background-color: #fff;
+  min-height: calc(100vh - 120px);
+  border-radius: 8px;
+  box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08);
+}
+
+.custom-tabs :deep(.el-tabs__nav-wrap::after) {
+  height: 1px;
+  background-color: #f0f0f0;
+}
+
+.custom-tabs :deep(.el-tabs__item) {
+  font-size: 15px;
+  font-weight: 500;
+  height: 50px;
+  line-height: 50px;
+  padding: 0 30px !important;
+}
+
+.custom-tabs :deep(.el-tabs__item.is-active) {
+  color: #1890ff;
+}
+
+.custom-tabs :deep(.el-tabs__active-bar) {
+  background-color: #1890ff;
+  height: 3px;
+}
+
+/* 各 Tab 内容容器:加入最大高度和优雅的滚动条,确保内容超过区域均可在区域内上下滑动 */
+.tab-content {
+  padding-top: 25px;
+  max-height: calc(100vh - 210px); /* 动态视窗高度自适应减扣 */
+  overflow-y: auto; /* 开启上下滑动 */
+  padding-right: 12px; /* 预留滚动条物理宽度防止排版挤压抖动 */
+}
+
+/* 高雅隐形纤细滚动条设计 */
+.tab-content::-webkit-scrollbar {
+  width: 6px;
+}
+
+.tab-content::-webkit-scrollbar-thumb {
+  background-color: rgba(0, 0, 0, 0.12);
+  border-radius: 4px;
+}
+
+.tab-content::-webkit-scrollbar-thumb:hover {
+  background-color: rgba(0, 0, 0, 0.24);
+}
+
+.tab-content::-webkit-scrollbar-track {
+  background: transparent;
+}
+
+.action-bar {
+  margin-bottom: 20px;
+  display: flex;
+  justify-content: flex-start;
+}
+
+.btn-primary-blue {
+  background-color: #1890ff;
+  border-color: #1890ff;
+}
+
+.btn-primary-blue:hover {
+  background-color: #40a9ff;
+  border-color: #40a9ff;
+}
+
+.text-blue {
+  color: #1890ff;
+}
+
+/* 表格样式 */
+.standard-table {
+  border-radius: 4px;
+  overflow: hidden;
+}
+
+:deep(.table-header-custom) {
+  background-color: #fafafa !important;
+  color: #333 !important;
+  font-weight: bold !important;
+  height: 54px;
+}
+
+.copyright-container {
+  background: #fff;
+  padding: 0;
+  border-radius: 8px;
+}
+
+.copyright-form {
+  max-width: 960px; /* 适当拉大表单最大宽度以容纳双列排布 */
+}
+
+.form-section {
+  margin-bottom: 30px;
+  background: #fcfcfc;
+  padding: 24px;
+  border-radius: 8px;
+  border: 1px solid #f0f0f0;
+}
+
+.section-title {
+  font-size: 16px;
+  font-weight: bold;
+  color: #333;
+  margin-bottom: 20px;
+  padding-left: 12px;
+  border-left: 4px solid #1890ff;
+}
+
+/* 网格布局:一排放2个字段 */
+.grid-form-fields {
+  display: grid;
+  grid-template-columns: 1fr 1fr; /* 完美平分两列 */
+  column-gap: 40px; /* 两列横向空隙极其通透 */
+  row-gap: 15px; /* 行间隙 */
+  align-items: center; /* 确保左右单元格在垂直方向上绝对居中对齐,杜绝高度拉伸错位! */
+}
+
+/* 确保网格内的表单项自身不带底边距,并强制水平横排 */
+.grid-form-fields :deep(.el-form-item) {
+  margin-bottom: 0 !important; /* 清除默认底边距对 Grid 单元格高度计算的物理干扰 */
+  display: flex !important;
+  align-items: center !important; /* 强制 label 与 input 纵向绝对水平线居中对齐! */
+}
+
+/* 确保所有表单标签横排 white-space nowrap 彻底防换行 */
+:deep(.el-form-item__label) {
+  white-space: nowrap !important;
+  word-break: keep-all !important;
+}
+
+/* 上传框样式 */
+.upload-box-rect {
+  width: 160px;
+  height: 78px;
+  border: 1px dashed #d9d9d9;
+  border-radius: 6px;
+  cursor: pointer;
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: center;
+  background: #fff;
+  transition: border-color 0.3s;
+}
+
+.upload-box-square {
+  width: 86px;
+  height: 86px;
+  border: 1px dashed #d9d9d9;
+  border-radius: 6px;
+  cursor: pointer;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  background: #fff;
+  transition: border-color 0.3s;
+  flex-shrink: 0;
+}
+
+.upload-box-rect:hover,
+.upload-box-square:hover {
+  border-color: #1890ff;
+}
+
+.preview-img-rect {
+  width: 100%;
+  height: 100%;
+  object-fit: contain;
+}
+
+.preview-img-square {
+  width: 100%;
+  height: 100%;
+  object-fit: contain;
+  padding: 5px;
+}
+
+.upload-icon {
+  font-size: 24px;
+  color: #999;
+}
+
+.upload-text {
+  font-size: 12px;
+  color: #999;
+  margin-top: 5px;
+}
+
+.field-tip {
+  font-size: 12px;
+  color: #999;
+  margin-top: 8px;
+  line-height: 1.5;
+}
+
+/* 社交媒体布局 */
+.social-config-row {
+  display: flex;
+  gap: 30px;
+}
+
+.social-item {
+  flex: 1;
+  background: #fff;
+  padding: 24px;
+  border-radius: 6px;
+  border: 1px solid #eee;
+}
+
+.social-label {
+  font-size: 14px;
+  font-weight: bold;
+  color: #666;
+  margin-bottom: 20px;
+  text-align: center;
+}
+
+.form-footer {
+  padding: 20px 0;
+  text-align: center;
+}
+
+/* 弹窗样式 */
+.custom-dialog :deep(.el-dialog__header) {
+  border-bottom: 1px solid #f0f0f0;
+  margin-right: 0;
+  padding-bottom: 15px;
+}
+
+.custom-dialog :deep(.el-dialog__title) {
+  font-size: 16px;
+  font-weight: bold;
+  color: #333;
+}
+
+.p-t-10 {
+  padding-top: 10px;
+}
+</style>

+ 22 - 30
src/views/system/basicSetting/index.vue

@@ -88,11 +88,6 @@
               <el-input v-model="form.feedbackLink" placeholder="请输入在线反馈链接" />
             </el-form-item>
           </el-col>
-          <el-col :span="8">
-            <el-form-item label="公众号图标" prop="wechatIcon">
-              <icon-select v-model="form.wechatIcon" width="100%" />
-            </el-form-item>
-          </el-col>
         </el-row>
 
         <!-- 第五行:公众号链接、微博图标、微博链接 -->
@@ -102,11 +97,7 @@
               <el-input v-model="form.wechatLink" placeholder="请输入公众号链接" />
             </el-form-item>
           </el-col>
-          <el-col :span="8">
-            <el-form-item label="微博图标" prop="weiboIcon">
-              <icon-select v-model="form.weiboIcon" width="100%" />
-            </el-form-item>
-          </el-col>
+
           <el-col :span="8">
             <el-form-item label="微博链接" prop="weiboLink">
               <el-input v-model="form.weiboLink" placeholder="请输入微博链接" />
@@ -118,29 +109,17 @@
         <el-row :gutter="20">
           <el-col :span="8">
             <el-form-item label="平台商城 diy" prop="platormDiy">
-              <el-switch
-                v-model="form.platormDiy"
-                active-value="1"
-                inactive-value="0"
-              />
+              <el-switch v-model="form.platormDiy" active-value="1" inactive-value="0" />
             </el-form-item>
           </el-col>
           <el-col :span="8">
             <el-form-item label="工业品 diy" prop="industrialDiy">
-              <el-switch
-                v-model="form.industrialDiy"
-                active-value="1"
-                inactive-value="0"
-              />
+              <el-switch v-model="form.industrialDiy" active-value="1" inactive-value="0" />
             </el-form-item>
           </el-col>
           <el-col :span="8">
             <el-form-item label="福利商城 diy" prop="fuliDiy">
-              <el-switch
-                v-model="form.fuliDiy"
-                active-value="1"
-                inactive-value="0"
-              />
+              <el-switch v-model="form.fuliDiy" active-value="1" inactive-value="0" />
             </el-form-item>
           </el-col>
         </el-row>
@@ -190,11 +169,24 @@
             </el-form-item>
           </el-col>
         </el-row>
+        <el-row :gutter="20">
+          <el-col :span="8">
+            <!-- 小程序二维码 -->
+            <el-form-item label="小程序二维码" prop="miniQrcode"> <upload-image v-model="form.miniQrcode" :limit="1" /> </el-form-item
+          ></el-col>
 
-        <!-- 小程序二维码 -->
-        <el-form-item label="小程序二维码" prop="miniQrcode">
-          <upload-image v-model="form.miniQrcode" :limit="1" />
-        </el-form-item>
+          <el-col :span="8">
+            <el-form-item label="微博图标" prop="weiboIcon">
+              <upload-image v-model="form.weiboIcon" :limit="1" />
+            </el-form-item>
+          </el-col>
+
+          <el-col :span="8">
+            <el-form-item label="公众号图标" prop="wechatIcon">
+              <upload-image v-model="form.wechatIcon" :limit="1" />
+            </el-form-item>
+          </el-col>
+        </el-row>
 
         <!-- 内容 -->
         <el-form-item label="内容" prop="content">
@@ -298,7 +290,7 @@ const submitForm = async () => {
     await formRef.value?.validate();
 
     const configKeys = Object.keys(form.value);
-    const batchData = configKeys.map(key => ({
+    const batchData = configKeys.map((key) => ({
       configType: '0',
       configKey: key,
       name: key,