Explorar o código

机构增加电话和logo

jinxia.mo hai 3 días
pai
achega
a7bb9bb496

+ 87 - 8
back-ui/src/components/ImageUpload/index.vue

@@ -3,18 +3,15 @@
     <el-upload
       multiple
       :disabled="disabled"
-      :action="uploadImgUrl"
+      :http-request="customUpload"
       list-type="picture-card"
-      :on-success="handleUploadSuccess"
       :before-upload="handleBeforeUpload"
-      :data="data"
       :limit="limit"
       :on-error="handleUploadError"
       :on-exceed="handleExceed"
       ref="imageUpload"
       :before-remove="handleDelete"
       :show-file-list="true"
-      :headers="headers"
       :file-list="fileList"
       :on-preview="handlePictureCardPreview"
       :class="{ hide: fileList.length >= limit }"
@@ -51,6 +48,7 @@
 import { getToken } from "@/utils/auth"
 import { isExternal } from "@/utils/validate"
 import Sortable from 'sortablejs'
+import request from "@/utils/request"
 
 const props = defineProps({
   modelValue: [String, Object, Array],
@@ -170,16 +168,91 @@ function handleExceed() {
   proxy.$modal.msgError(`上传文件数量不能超过 ${props.limit} 个!`)
 }
 
+// 自定义上传方法 - 通过后端获取签名后上传到OSS
+async function customUpload(options) {
+  const file = options.file
+  
+  try {
+    // 1. 从后端获取OSS签名
+    const signatureResponse = await request({
+      url: '/common/oss/signature',
+      method: 'get',
+      params: {
+        dir: 'dept/logo/'
+      }
+    })
+    
+    if (signatureResponse.code !== 200 || !signatureResponse.data) {
+      throw new Error(signatureResponse.msg || '获取OSS签名失败')
+    }
+    
+    const signature = signatureResponse.data
+    
+    // 2. 生成文件路径
+    const filePath = generateFilePath(file, signature.dir)
+    
+    // 3. 构建FormData,使用PostObject方式上传
+    const formData = new FormData()
+    formData.append('key', filePath)
+    formData.append('policy', signature.policy)
+    formData.append('OSSAccessKeyId', signature.accessKeyId)
+    formData.append('signature', signature.signature)
+    formData.append('file', file)
+    
+    // 4. 上传到OSS
+    const response = await fetch(signature.host, {
+      method: 'POST',
+      body: formData
+    })
+    
+    if (response.ok || response.status === 204) {
+      // 上传成功,返回OSS URL
+      const ossUrl = `${signature.host}/${filePath}`
+      handleUploadSuccess({
+        code: 200,
+        fileName: filePath,
+        url: ossUrl
+      }, file)
+    } else {
+      const errorText = await response.text()
+      throw new Error(`上传失败: ${response.status} ${errorText}`)
+    }
+  } catch (error) {
+    console.error('OSS上传失败:', error)
+    proxy.$modal.closeLoading()
+    proxy.$modal.msgError('上传图片失败: ' + (error.message || '未知错误'))
+    number.value--
+    if (proxy.$refs.imageUpload) {
+      proxy.$refs.imageUpload.handleRemove(file)
+    }
+  }
+}
+
+// 生成文件路径
+function generateFilePath(file, dir) {
+  const date = new Date()
+  const year = date.getFullYear()
+  const month = String(date.getMonth() + 1).padStart(2, '0')
+  const day = String(date.getDate()).padStart(2, '0')
+  const timestamp = Date.now()
+  const random = Math.random().toString(36).substring(2, 15)
+  const ext = file.name.substring(file.name.lastIndexOf('.'))
+  return `${dir}${year}/${month}/${day}/${timestamp}_${random}${ext}`
+}
+
 // 上传成功回调
 function handleUploadSuccess(res, file) {
   if (res.code === 200) {
-    uploadList.value.push({ name: res.fileName, url: res.fileName })
+    // 使用OSS的完整URL
+    uploadList.value.push({ name: res.fileName, url: res.url || res.fileName })
     uploadedSuccessfully()
   } else {
     number.value--
     proxy.$modal.closeLoading()
-    proxy.$modal.msgError(res.msg)
-    proxy.$refs.imageUpload.handleRemove(file)
+    proxy.$modal.msgError(res.msg || '上传失败')
+    if (proxy.$refs.imageUpload) {
+      proxy.$refs.imageUpload.handleRemove(file)
+    }
     uploadedSuccessfully()
   }
 }
@@ -223,7 +296,13 @@ function listToString(list, separator) {
   separator = separator || ","
   for (let i in list) {
     if (undefined !== list[i].url && list[i].url.indexOf("blob:") !== 0) {
-      strs += list[i].url.replace(baseUrl, "") + separator
+      // 如果是OSS URL,直接使用;否则去掉baseUrl
+      const url = list[i].url
+      if (url.startsWith('http://') || url.startsWith('https://')) {
+        strs += url + separator
+      } else {
+        strs += url.replace(baseUrl, "") + separator
+      }
     }
   }
   return strs != "" ? strs.substr(0, strs.length - 1) : ""

+ 107 - 0
back-ui/src/utils/oss.js

@@ -0,0 +1,107 @@
+/**
+ * 阿里云OSS上传工具类
+ * 直接上传到OSS,不经过服务器
+ */
+
+// OSS配置(从后端配置中读取,这里先写死,建议通过接口获取)
+const OSS_CONFIG = {
+  endpoint: 'oss-cn-beijing.aliyuncs.com',
+  bucket: 'mingxuejingbang',
+  accessKeyId: 'LTAI5tShe4frXAuHPGMnEjjY',
+  accessKeySecret: 'onbNqpaAfdcKU1fygjd2dQqJWPgpN2',
+  region: 'oss-cn-beijing'
+}
+
+/**
+ * 生成文件路径
+ * @param {File} file 文件对象
+ * @returns {string} 文件路径
+ */
+function generateFilePath(file) {
+  const date = new Date()
+  const year = date.getFullYear()
+  const month = String(date.getMonth() + 1).padStart(2, '0')
+  const day = String(date.getDate()).padStart(2, '0')
+  const timestamp = Date.now()
+  const random = Math.random().toString(36).substring(2, 15)
+  const ext = file.name.substring(file.name.lastIndexOf('.'))
+  return `dept/logo/${year}/${month}/${day}/${timestamp}_${random}${ext}`
+}
+
+/**
+ * 使用原生方式上传到OSS(使用FormData和PostObject)
+ * 注意:这种方式需要后端提供签名,为了简化,这里使用STS临时凭证方式
+ * 或者使用ali-oss SDK
+ */
+export async function uploadToOSS(file) {
+  return new Promise((resolve, reject) => {
+    // 生成文件路径
+    const filePath = generateFilePath(file)
+    
+    // 构建OSS上传URL
+    const host = `https://${OSS_CONFIG.bucket}.${OSS_CONFIG.endpoint}`
+    const url = `${host}/${filePath}`
+    
+    // 使用FormData上传
+    const formData = new FormData()
+    formData.append('key', filePath)
+    formData.append('file', file)
+    formData.append('policy', '') // 需要后端提供policy
+    formData.append('OSSAccessKeyId', OSS_CONFIG.accessKeyId)
+    formData.append('signature', '') // 需要后端提供签名
+    
+    // 注意:直接使用AccessKey不安全,建议使用STS临时凭证或后端签名
+    // 这里提供一个简化版本,实际应该通过后端接口获取签名
+    
+    fetch(url, {
+      method: 'PUT',
+      headers: {
+        'Content-Type': file.type
+      },
+      body: file
+    }).then(response => {
+      if (response.ok) {
+        resolve({
+          url: url,
+          fileName: filePath,
+          code: 200
+        })
+      } else {
+        reject(new Error('上传失败'))
+      }
+    }).catch(error => {
+      reject(error)
+    })
+  })
+}
+
+/**
+ * 使用ali-oss SDK上传(推荐方式)
+ * 需要先安装: npm install ali-oss
+ */
+export async function uploadToOSSWithSDK(file) {
+  // 动态导入ali-oss(如果已安装)
+  try {
+    const OSS = (await import('ali-oss')).default
+    
+    const client = new OSS({
+      region: OSS_CONFIG.region,
+      accessKeyId: OSS_CONFIG.accessKeyId,
+      accessKeySecret: OSS_CONFIG.accessKeySecret,
+      bucket: OSS_CONFIG.bucket
+    })
+    
+    const filePath = generateFilePath(file)
+    const result = await client.put(filePath, file)
+    
+    return {
+      url: result.url,
+      fileName: filePath,
+      code: 200
+    }
+  } catch (error) {
+    console.error('OSS SDK未安装或导入失败:', error)
+    throw error
+  }
+}
+

+ 18 - 5
back-ui/src/views/system/dept/index.vue

@@ -57,6 +57,12 @@
       >
          <el-table-column prop="deptName" label="机构名称" width="260"></el-table-column>
          <el-table-column prop="phone" label="机构电话" width="200"></el-table-column>
+         <el-table-column prop="logo" label="Logo" width="120">
+            <template #default="scope">
+               <image-preview v-if="scope.row.logo" :src="scope.row.logo" :width="50" :height="50" />
+            </template>
+         </el-table-column>
+         <el-table-column prop="contactPhone" label="联系电话" width="200"></el-table-column>
          <el-table-column prop="orderNum" label="排序" width="200"></el-table-column>
          <el-table-column prop="status" label="状态" width="100">
             <template #default="scope">
@@ -98,11 +104,6 @@
                      <el-input v-model="form.deptName" placeholder="请输入机构名称" />
                   </el-form-item>
                </el-col>
-              <el-col :span="12">
-                <el-form-item label="图标" prop="orderNum">
-                  <el-input controls-position="right" />
-                </el-form-item>
-              </el-col>
                <el-col :span="12">
                   <el-form-item label="显示排序" prop="orderNum">
                      <el-input-number v-model="form.orderNum" controls-position="right" :min="0" />
@@ -123,6 +124,16 @@
                      <el-input v-model="form.email" placeholder="请输入邮箱" maxlength="50" />
                   </el-form-item>
                </el-col>
+               <el-col :span="12">
+                  <el-form-item label="Logo" prop="logo">
+                     <image-upload v-model="form.logo" :limit="1" />
+                  </el-form-item>
+               </el-col>
+               <el-col :span="12">
+                  <el-form-item label="联系电话" prop="contactPhone">
+                     <el-input v-model="form.contactPhone" placeholder="请输入联系电话" maxlength="20" />
+                  </el-form-item>
+               </el-col>
                <el-col :span="12">
                   <el-form-item label="状态">
                      <el-radio-group v-model="form.status">
@@ -203,6 +214,8 @@ function reset() {
     leader: undefined,
     phone: undefined,
     email: undefined,
+    logo: undefined,
+    contactPhone: undefined,
     status: "0"
   }
   proxy.resetForm("deptRef")

+ 56 - 0
ie-admin/src/main/java/com/ruoyi/web/controller/common/CommonController.java

@@ -18,7 +18,10 @@ import com.ruoyi.common.core.domain.AjaxResult;
 import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.common.utils.file.FileUploadUtils;
 import com.ruoyi.common.utils.file.FileUtils;
+import com.ruoyi.common.utils.oss.OssUtils;
 import com.ruoyi.framework.config.ServerConfig;
+import org.springframework.beans.factory.annotation.Value;
+import java.util.Map;
 
 /**
  * 通用请求处理
@@ -34,6 +37,18 @@ public class CommonController
     @Autowired
     private ServerConfig serverConfig;
 
+    @Value("${oss.endpoint}")
+    private String ossEndpoint;
+
+    @Value("${oss.bucket}")
+    private String ossBucket;
+
+    @Value("${oss.accessKeyId}")
+    private String ossAccessKeyId;
+
+    @Value("${oss.accessKeySecret}")
+    private String ossAccessKeySecret;
+
     private static final String FILE_DELIMETER = ",";
 
     /**
@@ -159,4 +174,45 @@ public class CommonController
             log.error("下载文件失败", e);
         }
     }
+
+    /**
+     * 获取OSS上传签名
+     * 
+     * @param dir 上传目录,例如 "dept/logo/"
+     * @return OSS签名信息
+     */
+    @GetMapping("/oss/signature")
+    public AjaxResult getOssSignature(@org.springframework.web.bind.annotation.RequestParam(required = false, defaultValue = "dept/logo/") String dir)
+    {
+        try
+        {
+            // 确保目录以/结尾
+            if (!dir.endsWith("/"))
+            {
+                dir = dir + "/";
+            }
+            
+            // 生成签名,有效期1小时
+            Map<String, String> signature = OssUtils.generatePostPolicy(
+                ossEndpoint, 
+                ossAccessKeyId, 
+                ossAccessKeySecret, 
+                ossBucket, 
+                dir, 
+                3600
+            );
+            
+            if (signature == null)
+            {
+                return AjaxResult.error("生成OSS签名失败");
+            }
+            
+            return AjaxResult.success(signature);
+        }
+        catch (Exception e)
+        {
+            log.error("获取OSS签名失败", e);
+            return AjaxResult.error("获取OSS签名失败: " + e.getMessage());
+        }
+    }
 }

+ 61 - 1
ie-admin/src/main/java/com/ruoyi/web/controller/front/UserController.java

@@ -6,6 +6,7 @@ import com.ruoyi.common.annotation.Log;
 import com.ruoyi.common.core.content.VistorContextHolder;
 import com.ruoyi.common.core.controller.BaseController;
 import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.domain.entity.SysDept;
 import com.ruoyi.common.core.domain.entity.SysUser;
 import com.ruoyi.common.core.domain.model.LoginBody;
 import com.ruoyi.common.core.domain.model.LoginCard;
@@ -17,12 +18,14 @@ import com.ruoyi.common.enums.BusinessType;
 import com.ruoyi.common.enums.ExamType;
 import com.ruoyi.common.utils.NumberUtils;
 import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.dz.domain.DzAgent;
 import com.ruoyi.dz.domain.DzCards;
 import com.ruoyi.dz.domain.DzClasses;
 import com.ruoyi.dz.domain.DzControl;
 import com.ruoyi.dz.domain.DzSchool;
 import com.ruoyi.dz.mapper.DzClassesMapper;
 import com.ruoyi.dz.mapper.DzSchoolMapper;
+import com.ruoyi.dz.service.IDzAgentService;
 import com.ruoyi.dz.service.IDzCardsService;
 import com.ruoyi.dz.service.IDzClassesService;
 import com.ruoyi.dz.service.IDzControlService;
@@ -33,6 +36,7 @@ import com.ruoyi.enums.UserTypeEnum;
 import com.ruoyi.framework.web.service.SysPermissionService;
 import com.ruoyi.framework.web.service.TokenService;
 import com.ruoyi.system.service.ISysConfigService;
+import com.ruoyi.system.service.ISysDeptService;
 import com.ruoyi.system.service.ISysUserService;
 import com.ruoyi.web.service.CommService;
 import com.ruoyi.web.service.SysLoginService;
@@ -65,8 +69,10 @@ public class UserController extends BaseController {
     private final IDzClassesService dzClassesService;
     private final DzSchoolMapper dzSchoolMapper;
     private final DzClassesMapper dzClassesMapper;
+    private final IDzAgentService agentService;
+    private final ISysDeptService deptService;
 
-    public UserController(IDzControlService dzControlService, SysLoginService loginService, ISysUserService userService, SysPermissionService permissionService, TokenService tokenService, CommService commService, ISysConfigService configService, IDzCardsService dzCardsService, IDzSchoolService dzSchoolService, IDzClassesService dzClassesService, DzSchoolMapper dzSchoolMapper, DzClassesMapper dzClassesMapper) {
+    public UserController(IDzControlService dzControlService, SysLoginService loginService, ISysUserService userService, SysPermissionService permissionService, TokenService tokenService, CommService commService, ISysConfigService configService, IDzCardsService dzCardsService, IDzSchoolService dzSchoolService, IDzClassesService dzClassesService, DzSchoolMapper dzSchoolMapper, DzClassesMapper dzClassesMapper, IDzAgentService agentService, ISysDeptService deptService) {
         this.dzControlService = dzControlService;
         this.loginService = loginService;
         this.userService = userService;
@@ -79,6 +85,8 @@ public class UserController extends BaseController {
         this.dzClassesService = dzClassesService;
         this.dzSchoolMapper = dzSchoolMapper;
         this.dzClassesMapper = dzClassesMapper;
+        this.agentService = agentService;
+        this.deptService = deptService;
     }
 
     @GetMapping(value = "provinces")
@@ -239,6 +247,58 @@ public class UserController extends BaseController {
         ajax.put("isDefaultModifyPwd", commService.initPasswordIsModify(user.getPwdUpdateDate()));
         ajax.put("isPasswordExpired", commService.passwordIsExpiration(user.getPwdUpdateDate()));
 
+        // 添加组织信息.卡号/邀请码开始找:再逐步找到 代理商-机构
+        Long agentId = null;
+        if(null != user.getCardId()) {
+            DzCards cards = dzCardsService.selectDzCardsByCardId(user.getCardId());
+            if(null != cards) {
+                agentId = cards.getAgentId();
+            }
+        }else{
+            if (null != user.getInviteCode()) {
+                String inviteCode = user.getInviteCode();
+                // 如果邀请码全部是数字,则转换为Long
+                if (NumberUtils.isNumeric(inviteCode)) {
+                    try {
+                        agentId = Long.parseLong(inviteCode);
+                    } catch (NumberFormatException e) {
+                        // 如果转换失败,保持为null
+                        agentId = null;
+                    }
+                }
+            }
+        }
+
+        // 通过代理商查询机构信息
+        Long deptId = null;
+        if (null != agentId) {
+            DzAgent agent = agentService.selectDzAgentByAgentId(agentId);
+            if(null != agent && null != agent.getDeptId()) {
+                deptId = agent.getDeptId();
+            }
+        }else{
+            //默认使用单招一卡通
+            deptId = 101L;
+        }
+        
+        // 构建组织信息对象
+        // 查询机构信息
+        SysDept dept = deptService.selectDeptById(deptId);
+        JSONObject org = new JSONObject();
+        if(null != dept) {
+            // 优先使用机构中的信息
+            if(StringUtils.isNotBlank(dept.getLogo())) {
+                org.put("logo", dept.getLogo());
+            }
+            if(StringUtils.isNotBlank(dept.getDeptName())) {
+                org.put("orgName", dept.getDeptName());
+            }
+            if(StringUtils.isNotBlank(dept.getContactPhone())) {
+                org.put("contactPhone", dept.getContactPhone());
+            }
+        }
+        ajax.put("org", org);
+
         //获取app的配置文件
         String type = request.getHeader("type");
         //H5 wechat frontApp均需要菜单

+ 30 - 0
ie-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDept.java

@@ -43,6 +43,12 @@ public class SysDept extends BaseEntity
     /** 邮箱 */
     private String email;
 
+    /** Logo */
+    private String logo;
+
+    /** 联系电话(机构联系电话) */
+    private String contactPhone;
+
     /** 机构状态:0正常,1停用 */
     private String status;
 
@@ -153,6 +159,28 @@ public class SysDept extends BaseEntity
         this.email = email;
     }
 
+    @Size(min = 0, max = 500, message = "Logo URL长度不能超过500个字符")
+    public String getLogo()
+    {
+        return logo;
+    }
+
+    public void setLogo(String logo)
+    {
+        this.logo = logo;
+    }
+
+    @Size(min = 0, max = 20, message = "联系电话长度不能超过20个字符")
+    public String getContactPhone()
+    {
+        return contactPhone;
+    }
+
+    public void setContactPhone(String contactPhone)
+    {
+        this.contactPhone = contactPhone;
+    }
+
     public String getStatus()
     {
         return status;
@@ -204,6 +232,8 @@ public class SysDept extends BaseEntity
             .append("leader", getLeader())
             .append("phone", getPhone())
             .append("email", getEmail())
+            .append("logo", getLogo())
+            .append("contactPhone", getContactPhone())
             .append("status", getStatus())
             .append("delFlag", getDelFlag())
             .append("createBy", getCreateBy())

+ 105 - 0
ie-common/src/main/java/com/ruoyi/common/utils/oss/OssUtils.java

@@ -0,0 +1,105 @@
+package com.ruoyi.common.utils.oss;
+
+import com.aliyun.oss.OSS;
+import com.aliyun.oss.OSSClientBuilder;
+import com.aliyun.oss.common.utils.BinaryUtil;
+import com.aliyun.oss.model.MatchMode;
+import com.aliyun.oss.model.PolicyConditions;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.nio.charset.StandardCharsets;
+import java.util.*;
+
+/**
+ * 阿里云OSS工具类
+ * 
+ * @author ruoyi
+ */
+public class OssUtils
+{
+    private static final Logger log = LoggerFactory.getLogger(OssUtils.class);
+
+    /**
+     * 生成OSS上传签名
+     * 
+     * @param endpoint OSS endpoint
+     * @param accessKeyId AccessKey ID
+     * @param accessKeySecret AccessKey Secret
+     * @param bucket Bucket名称
+     * @param dir 上传目录,例如 "dept/logo/"
+     * @param expireTime 过期时间(秒),默认1小时
+     * @return 签名信息
+     */
+    public static Map<String, String> generatePostPolicy(String endpoint, String accessKeyId, 
+            String accessKeySecret, String bucket, String dir, long expireTime)
+    {
+        try
+        {
+            if (expireTime <= 0)
+            {
+                expireTime = 3600; // 默认1小时
+            }
+
+            long expireEndTime = System.currentTimeMillis() + expireTime * 1000;
+            Date expiration = new Date(expireEndTime);
+            PolicyConditions policyConds = new PolicyConditions();
+            policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, 1048576000); // 最大1GB
+            policyConds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, dir);
+
+            // 使用OSS Client生成PostPolicy
+            OSS ossClient = new OSSClientBuilder().build("https://" + endpoint, accessKeyId, accessKeySecret);
+            String postPolicy = ossClient.generatePostPolicy(expiration, policyConds);
+            byte[] binaryData = postPolicy.getBytes(StandardCharsets.UTF_8);
+            String encodedPolicy = BinaryUtil.toBase64String(binaryData);
+            String postSignature = ossClient.calculatePostSignature(postPolicy);
+            
+            ossClient.shutdown();
+
+            Map<String, String> respMap = new LinkedHashMap<>();
+            respMap.put("accessKeyId", accessKeyId);
+            respMap.put("policy", encodedPolicy);
+            respMap.put("signature", postSignature);
+            respMap.put("dir", dir);
+            respMap.put("host", "https://" + bucket + "." + endpoint);
+            respMap.put("expire", String.valueOf(expireEndTime / 1000));
+
+            return respMap;
+        }
+        catch (Exception e)
+        {
+            log.error("生成OSS签名失败", e);
+            return null;
+        }
+    }
+
+    /**
+     * 生成文件路径
+     * 
+     * @param originalFilename 原始文件名
+     * @param dir 目录前缀
+     * @return 文件路径
+     */
+    public static String generateFilePath(String originalFilename, String dir)
+    {
+        Date date = new Date();
+        Calendar calendar = Calendar.getInstance();
+        calendar.setTime(date);
+        
+        int year = calendar.get(Calendar.YEAR);
+        int month = calendar.get(Calendar.MONTH) + 1;
+        int day = calendar.get(Calendar.DAY_OF_MONTH);
+        
+        String ext = "";
+        if (originalFilename != null && originalFilename.contains("."))
+        {
+            ext = originalFilename.substring(originalFilename.lastIndexOf("."));
+        }
+        
+        String timestamp = String.valueOf(System.currentTimeMillis());
+        String random = UUID.randomUUID().toString().replace("-", "").substring(0, 8);
+        
+        return dir + year + "/" + String.format("%02d", month) + "/" + String.format("%02d", day) + "/" + timestamp + "_" + random + ext;
+    }
+}
+

+ 11 - 3
ie-system/src/main/resources/mapper/system/SysDeptMapper.xml

@@ -13,6 +13,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 		<result property="leader"     column="leader"      />
 		<result property="phone"      column="phone"       />
 		<result property="email"      column="email"       />
+		<result property="logo"       column="logo"        />
+		<result property="contactPhone" column="contact_phone" />
 		<result property="status"     column="status"      />
 		<result property="delFlag"    column="del_flag"    />
 		<result property="parentName" column="parent_name" />
@@ -23,7 +25,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 	</resultMap>
 	
 	<sql id="selectDeptVo">
-        select d.dept_id, d.parent_id, d.ancestors, d.dept_name, d.order_num, d.leader, d.phone, d.email, d.status, d.del_flag, d.create_by, d.create_time 
+        select d.dept_id, d.parent_id, d.ancestors, d.dept_name, d.order_num, d.leader, d.phone, d.email, d.logo, d.contact_phone, d.status, d.del_flag, d.create_by, d.create_time 
         from sys_dept d
     </sql>
     
@@ -59,14 +61,14 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 	</select>
     
     <select id="selectDeptById" parameterType="Long" resultMap="SysDeptResult">
-		select d.dept_id, d.parent_id, d.ancestors, d.dept_name, d.order_num, d.leader, d.phone, d.email, d.status,
+		select d.dept_id, d.parent_id, d.ancestors, d.dept_name, d.order_num, d.leader, d.phone, d.email, d.logo, d.contact_phone, d.status,
 			(select dept_name from sys_dept where dept_id = d.parent_id) parent_name
 		from sys_dept d
 		where d.dept_id = #{deptId}
 	</select>
 
 	<select id="selectDeptByIds" resultMap="SysDeptResult">
-		select d.dept_id, d.parent_id, d.ancestors, d.dept_name, d.order_num, d.leader, d.phone, d.email, d.status
+		select d.dept_id, d.parent_id, d.ancestors, d.dept_name, d.order_num, d.leader, d.phone, d.email, d.logo, d.contact_phone, d.status
 		from sys_dept d
 		where d.dept_id in <foreach collection="ids" item="id" open="(" separator="," close=")">#{id}</foreach>
 	</select>
@@ -103,6 +105,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  			<if test="leader != null and leader != ''">leader,</if>
  			<if test="phone != null and phone != ''">phone,</if>
  			<if test="email != null and email != ''">email,</if>
+ 			<if test="logo != null and logo != ''">logo,</if>
+ 			<if test="contactPhone != null and contactPhone != ''">contact_phone,</if>
  			<if test="status != null">status,</if>
  			<if test="createBy != null and createBy != ''">create_by,</if>
  			create_time
@@ -115,6 +119,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  			<if test="leader != null and leader != ''">#{leader},</if>
  			<if test="phone != null and phone != ''">#{phone},</if>
  			<if test="email != null and email != ''">#{email},</if>
+ 			<if test="logo != null and logo != ''">#{logo},</if>
+ 			<if test="contactPhone != null and contactPhone != ''">#{contactPhone},</if>
  			<if test="status != null">#{status},</if>
  			<if test="createBy != null and createBy != ''">#{createBy},</if>
  			sysdate()
@@ -131,6 +137,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  			<if test="leader != null">leader = #{leader},</if>
  			<if test="phone != null">phone = #{phone},</if>
  			<if test="email != null">email = #{email},</if>
+ 			<if test="logo != null">logo = #{logo},</if>
+ 			<if test="contactPhone != null">contact_phone = #{contactPhone},</if>
  			<if test="status != null and status != ''">status = #{status},</if>
  			<if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if>
  			update_time = sysdate()

+ 9 - 0
sql/add_dept_logo_contact_phone.sql

@@ -0,0 +1,9 @@
+-- 为 sys_dept 表添加 logo 和 contact_phone 字段
+-- 执行时间:2025年
+
+-- 添加 logo 字段
+ALTER TABLE sys_dept ADD COLUMN logo VARCHAR(500) DEFAULT NULL COMMENT 'Logo' AFTER email;
+
+-- 添加 contact_phone 字段
+ALTER TABLE sys_dept ADD COLUMN contact_phone VARCHAR(20) DEFAULT NULL COMMENT '联系电话(机构联系电话)' AFTER logo;
+