Ver Fonte

Merge branch 'master' of http://210.51.45.41:3000/itcat_admin/aws_donenow

HULEI há 2 meses atrás
pai
commit
ae6b1e2cd3

+ 11 - 1
com.awspaas.user.apps.donenow_ctt/src/com/awspaas/user/apps/donenow_ctt/controller/contractCreateController.java

@@ -278,6 +278,15 @@ public class contractCreateController {
             if (DBSql.getInt("SELECT count(1) FROM BO_EU_DNCTT_CONTRACT_SERVICE_PERIOD WHERE APPROVE_AND_POST_USER_ID IS NOT NULL AND LENGTH(APPROVE_AND_POST_USER_ID)>1 AND APPROVE_AND_POST_DATE IS NOT NULL and CONTRACT_ID=? and CONTRACT_SERVICE_ID=? ", new Object[]{service.get("CONTRACT_ID"), service.get("ID")}) > 0) {
                 return ResponseObject.newErrResponse("已审批合同服务,无法删除!");
             }
+
+            String CONTRACT_COST_ID = DBSql.getString("SELECT ID FROM BO_EU_DNCTT_CONTRACT_COST WHERE IS_SERVICE_PRODUCT=1 AND SERVICE_ID=?", new Object[]{service.get("ID")});
+
+            if (StringUtils.isNotBlank(CONTRACT_COST_ID)) {
+                //采购订单相关也有删除
+                List<BO> costProducts = SDK.getBOAPI().query("BO_EU_DNCTT_CONTRACT_COST_PRODUCT").addQuery("CONTRACT_COST_ID =", CONTRACT_COST_ID).list();
+                if (costProducts.size() > 0)
+                    return ResponseObject.newErrResponse("已经生成采购订单,请先删除采购订单");
+            }
         }
 
         for (RowMap service : serviceList) {
@@ -301,7 +310,8 @@ public class contractCreateController {
 
             DBSql.update("delete from BO_EU_DNCTT_CONTRACT_SERVICE_EDIT where  CONTRACT_SERVICE_ID=?", new Object[]{service.get("ID")});
 
-            DBSql.update("delete from BO_EU_DNCTT_CONTRACT_COST where  IS_SERVICE_PRODUCT=1 AND SERVICE_ID=?", new Object[]{service.get("ID")});
+            DBSql.update("delete from BO_EU_DNCTT_CONTRACT_COST where IS_SERVICE_PRODUCT=1 AND SERVICE_ID=?", new Object[]{service.get("ID")});
+
         }
 
         return ResponseObject.newOkResponse();

+ 1 - 1
com.awspaas.user.apps.donenow_ctt/src/com/awspaas/user/apps/donenow_ctt/controller/invoiceController.java

@@ -76,7 +76,7 @@ public class invoiceController {
     public ResponseObject delInvoicePlan(UserContext uc, String bindids) {
 
         for (String bindid : bindids.split(",")) {
-            SDK.getProcessAPI().remindMailById(uc.getUID(), bindid);
+            SDK.getProcessAPI().deleteById(bindid, uc.getUID());
             SDK.getBOAPI().removeByBindId("BO_EU_DNCTT_INVOICE_PLAN_DETAIL", bindid);
             SDK.getBOAPI().removeByBindId("BO_EU_DNCTT_INVOICE_PLAN", bindid);
         }

+ 69 - 0
com.awspaas.user.apps.donenow_ctt/src/com/awspaas/user/apps/donenow_ctt/service/CityAbbreviationUtil.java

@@ -0,0 +1,69 @@
+package com.awspaas.user.apps.donenow_ctt.service;
+
+import net.sourceforge.pinyin4j.PinyinHelper;
+import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType;
+import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;
+import net.sourceforge.pinyin4j.format.HanyuPinyinToneType;
+import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination;
+
+public class CityAbbreviationUtil {
+
+    // 处理城市名称,去除常见后缀(如"市"、"省"等)
+    private static String processCityName(String city) {
+        if (city == null || city.trim().isEmpty()) {
+            return "";
+        }
+        // 定义需要去除的后缀
+        String[] suffixes = {"市", "省", "自治区", "自治州", "地区", "盟", "县", "区"};
+        for (String suffix : suffixes) {
+            if (city.endsWith(suffix)) {
+                return city.substring(0, city.length() - suffix.length());
+            }
+        }
+        return city;
+    }
+
+    // 获取单个汉字的拼音首字母(大写)
+    private static char getFirstLetter(char chineseChar) {
+        HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat();
+        format.setCaseType(HanyuPinyinCaseType.UPPERCASE); // 首字母大写
+        format.setToneType(HanyuPinyinToneType.WITHOUT_TONE); // 不带声调
+
+        try {
+            // 多音字可能返回多个拼音,取第一个
+            String[] pinyinArray = PinyinHelper.toHanyuPinyinStringArray(chineseChar, format);
+            if (pinyinArray != null && pinyinArray.length > 0) {
+                return pinyinArray[0].charAt(0); // 返回首字母
+            }
+        } catch (BadHanyuPinyinOutputFormatCombination e) {
+            e.printStackTrace();
+        }
+        return chineseChar; // 非汉字直接返回原字符
+    }
+
+    // 生成城市拼音首字母缩写
+    public static String getCityAbbreviation(String city) {
+        String processedCity = processCityName(city);
+        if (processedCity.isEmpty()) {
+            return "";
+        }
+
+        StringBuilder abbreviation = new StringBuilder();
+        for (int i = 0; i < processedCity.length(); i++) {
+            char c = processedCity.charAt(i);
+            abbreviation.append(getFirstLetter(c));
+        }
+        return abbreviation.toString();
+    }
+
+    // 测试
+    public static void main(String[] args) {
+        String cssx = "上海市";
+        System.out.println(getCityAbbreviation(cssx)); // 输出:SH
+
+        // 其他测试案例
+        System.out.println(getCityAbbreviation("北京市")); // 输出:BJ
+        System.out.println(getCityAbbreviation("广州市")); // 输出:GZ
+        System.out.println(getCityAbbreviation("四川省")); // 输出:SC
+    }
+}

+ 29 - 2
com.awspaas.user.apps.donenow_ctt/src/com/awspaas/user/apps/donenow_ctt/service/contractService.java

@@ -21,6 +21,8 @@ import java.time.temporal.ChronoUnit;
 import java.time.temporal.TemporalAdjusters;
 import java.util.*;
 
+import static com.awspaas.user.apps.donenow_ctt.service.CityAbbreviationUtil.getCityAbbreviation;
+
 
 /**
  * 合同服务
@@ -121,7 +123,8 @@ public class contractService {
                 DBSql.update("update BO_EU_DNCTT_CONTRACT set IS_SDT_DEFAULT=0 where ACCOUNT_ID=?", new Object[]{contractBO.getString("ACCOUNT_ID")});
             }
 
-            if (idApply) SDK.getBOAPI().update("BO_EU_DNCTT_CONTRACT_APPLY", contractBO);//更新合同
+            if (idApply)
+                SDK.getBOAPI().update("BO_EU_DNCTT_CONTRACT_APPLY", contractBO);//更新合同
             else {
                 dn.recordFormChanges.record(uc, contractBO, "合同编辑");
                 SDK.getBOAPI().update("BO_EU_DNCTT_CONTRACT", contractBO);
@@ -135,7 +138,8 @@ public class contractService {
 
             RowMap dto = new RowMap(contractBO.asMap());//合同对象
 
-            if (idApply) insertContract(uc, dto);//创建合同详情,用于提交后查看和修改相关配置项、工单、服务等
+            if (idApply)
+                insertContract(uc, dto);//创建合同详情,用于提交后查看和修改相关配置项、工单、服务等
             else {
                 //更新
                 DBSql.update("update BO_EU_DNCTT_CONTRACT_RATE set CONTRACT_ID=? where BINDID=?", new Object[]{dto.getString("ID"), dto.getString("BINDID")});
@@ -229,6 +233,29 @@ public class contractService {
             contractBO.set("APPLY_ID", APPLY_ID);
             contractBO.setBindId(contractInstance.getId());
 
+            //我现在用的规则是 销售合同以XHT-SH(以公司所在城市拼音首位字母缩写)-20251013(录入日期的年月)-00001(以保存先后顺序从1开始排以此类推)  XHT-SH-20220624-00636像这样的
+            //2025年10月25日  生成合同编号
+
+            String contractNo = SDK.getRuleAPI().executeAtScript("@sequenceYear(@companyId_contract,5)");
+
+            String DISTRICT_ID = DBSql.getString("select DISTRICT_ID from BO_EU_DNCRM_ACCOUNT where ID=?", new Object[]{contract.getString("ACCOUNT_ID")});
+
+            String cssx = "SH";//城市缩写
+
+            if (StringUtils.isNotBlank(DISTRICT_ID)) {
+                RowMap city = DBSql.getMap("SELECT EXTTEXT1,EXTTEXT2 FROM BO_ACT_DICT_KV_ITEM WHERE DICTKEY = 'GB.ADDR' AND ITEMNO= ?", new Object[]{DISTRICT_ID});
+                if (city != null) {
+                    cssx = city.getString("EXTTEXT1");
+                    if (!cssx.contains("市")) {
+                        cssx = city.getString("EXTTEXT2");
+                    }
+                    //如果 cssx="上海市" 则输出 SH
+                    cssx = getCityAbbreviation(cssx);
+                }
+            }
+            contractNo = "XHT-" + cssx + "-" + LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd")) + "-" + contractNo;
+            contractBO.set("NO", contractNo);
+
             SDK.getBOAPI().createDataBO("BO_EU_DNCTT_CONTRACT", contractBO, uc);
             dn.recordFormChanges.record(uc, contractBO, "合同新增");
 

+ 15 - 10
com.awspaas.user.apps.donenow_ivt/src/com/awspaas/user/apps/donenow_ivt/controller/caiController.java

@@ -1,20 +1,16 @@
 package com.awspaas.user.apps.donenow_ivt.controller;
 
+import com.actionsoft.bpms.bo.engine.BO;
 import com.actionsoft.bpms.bpmn.engine.model.run.delegate.ProcessInstance;
+import com.actionsoft.bpms.commons.database.RowMap;
 import com.actionsoft.bpms.commons.mvc.view.ResponseObject;
+import com.actionsoft.bpms.server.UserContext;
 import com.actionsoft.bpms.server.bind.annotation.Controller;
 import com.actionsoft.bpms.server.bind.annotation.Mapping;
-import com.actionsoft.bpms.server.UserContext;
 import com.actionsoft.bpms.util.DBSql;
 import com.actionsoft.sdk.local.SDK;
 import org.apache.commons.lang3.StringUtils;
-import com.actionsoft.bpms.commons.database.RowMap;
-import com.actionsoft.bpms.bo.engine.BO;
-
 
-import java.sql.Connection;
-import java.sql.SQLException;
-import java.util.*;
 import java.util.*;
 
 @Controller
@@ -53,6 +49,7 @@ public class caiController {
         responseObject.setData(resultList);
         return responseObject;
     }
+
     @Mapping(value = "com.awspaas.user.apps.donenow_ivt.queryCount")
     public ResponseObject queryPurchaseItemCount(UserContext uc, String orderId) {
         if (StringUtils.isBlank(orderId)) {
@@ -72,6 +69,7 @@ public class caiController {
 
         return responseObject;
     }
+
     @Mapping(value = "com.awspaas.user.apps.donenow_ivt.queryPaymentPlan")
     public ResponseObject queryPaymentPlan(UserContext uc, String orderId) {
         if (StringUtils.isBlank(orderId)) {
@@ -156,7 +154,6 @@ public class caiController {
     }
 
 
-
     @Mapping(value = "com.awspaas.user.apps.donenow_ivt.queryPayAmount")
     public ResponseObject queryPayAmount(UserContext uc, String orderId) {
         if (StringUtils.isBlank(orderId)) {
@@ -260,6 +257,15 @@ public class caiController {
             bo.set("PLAN_DATE", planDate);
             bo.set("PLAN_AMOUNT", planAmount);
             bo.set("ACCOUNT_PAYEE", vendorAccountId);
+
+            String orderProductNames = DBSql.getString("SELECT GROUP_CONCAT(NAME SEPARATOR '、') FROM BO_EU_DNIVT_ORDER_PRODUCT WHERE ORDER_ID=?", new Object[]{orderId});
+            //最长300个字符,需要截取
+            if (orderProductNames.length() > 300) {
+                orderProductNames = orderProductNames.substring(0, 300);
+            }
+            //付款说明
+            bo.set("PAY_DESC", orderProductNames);
+
             SDK.getBOAPI().createDataBO("BO_EU_DNIVT_ORDER_PAYMENT_PLAN", bo, uc);
 
             // 组装返回结果(与queryPayAmount风格一致)
@@ -384,6 +390,7 @@ public class caiController {
             return ResponseObject.newErrResponse("查询失败:" + e.getMessage());
         }
     }
+
     @Mapping(value = "com.awspaas.user.apps.donenow_ivt.queryContractByDes")
     public ResponseObject queryContractByDes(UserContext uc, String des) {
         if (StringUtils.isBlank(des)) {
@@ -415,6 +422,4 @@ public class caiController {
     }
 
 
-
-
 }

+ 38 - 1
com.awspaas.user.apps.donenow_ivt/src/com/awspaas/user/apps/donenow_ivt/controller/ivtOrderController.java

@@ -23,12 +23,17 @@ import org.apache.commons.lang3.StringUtils;
 import java.sql.Connection;
 import java.sql.SQLException;
 import java.text.SimpleDateFormat;
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
 import java.util.*;
 import java.util.stream.Collectors;
 import java.math.BigDecimal;
 import java.math.RoundingMode;
 import java.util.HashMap;
 import java.util.Map;
+
+import static com.awspaas.user.apps.donenow_ivt.utils.CityAbbreviationUtil.getCityAbbreviation;
+
 @Controller
 public class ivtOrderController {
     /**
@@ -731,7 +736,6 @@ public class ivtOrderController {
             if (VENDOR_ACCOUNT_ID.size() == 1) {
                 purchaseOrder.set("VENDOR_ACCOUNT_ID", VENDOR_ACCOUNT_ID.stream().findFirst().get());
             }
-
             SDK.getBOAPI().createDataBO("BO_EU_DNIVT_ORDER", purchaseOrder, uc, conn);
             System.out.println("采购单创建成功,ID: " + purchaseOrder.getId());
 
@@ -871,4 +875,37 @@ public class ivtOrderController {
         return ResponseObject.newOkResponse();
     }
 
+
+    /**
+     * 删除采购订单
+     * @param uc
+     * @param bindId
+     * @return
+     */
+    @Mapping("com.awspaas.user.apps.donenow_ivt.deleteOrder")
+    public ResponseObject deleteOrder(UserContext uc, String bindId) {
+        BO order = SDK.getBOAPI().getByProcess("BO_EU_DNIVT_ORDER", bindId);
+
+        List<BO> orderProducts = SDK.getBOAPI().query("BO_EU_DNIVT_ORDER_PRODUCT").addQuery("BINDID =", bindId).list();
+
+        if (order.isEnd())
+            return ResponseObject.newErrResponse("采购订单已结束,不能删除");
+
+        if (order.getString("ISEND").equals("1"))
+            return ResponseObject.newErrResponse("采购订单已结束,不能删除");
+
+        SDK.getProcessAPI().deleteById(bindId, uc.getUID());
+
+        for (BO op : orderProducts) {
+            String costProductID = DBSql.getString("SELECT ID FROM BO_EU_DNCTT_CONTRACT_COST_PRODUCT WHERE ORDER_ID=? AND CONTRACT_COST_ID=?", new Object[]{op.getString("ORDER_ID"), op.getString("CONTRACT_COST_ID")});
+
+            if (StringUtils.isNotBlank(costProductID))
+                DBSql.update("delete from BO_EU_DNCTT_CONTRACT_COST_PRODUCT where ID=?", new Object[]{costProductID});
+        }
+
+        SDK.getBOAPI().removeByBindId("BO_EU_DNIVT_ORDER", bindId);
+        SDK.getBOAPI().removeByBindId("BO_EU_DNIVT_ORDER_PRODUCT", bindId);
+        return ResponseObject.newOkResponse();
+    }
+
 }

+ 33 - 0
com.awspaas.user.apps.donenow_ivt/src/com/awspaas/user/apps/donenow_ivt/event/ivtOrderFormAfter.java

@@ -3,10 +3,17 @@ package com.awspaas.user.apps.donenow_ivt.event;
 import com.actionsoft.bpms.bo.engine.BO;
 import com.actionsoft.bpms.bpmn.engine.core.delegate.ProcessExecutionContext;
 import com.actionsoft.bpms.bpmn.engine.listener.ExecuteListener;
+import com.actionsoft.bpms.commons.database.RowMap;
+import com.actionsoft.bpms.util.DBSql;
 import com.actionsoft.sdk.local.SDK;
+import org.apache.commons.lang3.StringUtils;
 
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
 import java.util.List;
 
+import static com.awspaas.user.apps.donenow_ivt.utils.CityAbbreviationUtil.getCityAbbreviation;
+
 public class ivtOrderFormAfter extends ExecuteListener {
     public String getDescription() {
         return "采购订单表单保存后,数据处理事件";
@@ -39,5 +46,31 @@ public class ivtOrderFormAfter extends ExecuteListener {
         }
 
 
+        //采购订单编号
+
+        String purchaseOrderNo = SDK.getRuleAPI().executeAtScript("@sequenceYear(@companyId_purchase_order,4,0,130)");
+
+        String DISTRICT_ID = DBSql.getString("select DISTRICT_ID from BO_EU_DNCRM_ACCOUNT where ID=?", new Object[]{orderBO.getString("VENDOR_ACCOUNT_ID")});
+
+        String cssx = "SH";//城市缩写
+
+        if (StringUtils.isNotBlank(DISTRICT_ID)) {
+            RowMap city = DBSql.getMap("SELECT EXTTEXT1,EXTTEXT2 FROM BO_ACT_DICT_KV_ITEM WHERE DICTKEY = 'GB.ADDR' AND ITEMNO= ?", new Object[]{DISTRICT_ID});
+            if (city != null) {
+                cssx = city.getString("EXTTEXT1");
+                if (!cssx.contains("市")) {
+                    cssx = city.getString("EXTTEXT2");
+                }
+                //如果 cssx="上海市" 则输出 SH
+                cssx = getCityAbbreviation(cssx);
+            }
+        }
+        purchaseOrderNo = "CHT-" + cssx + "-" + LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd")) + "-" + purchaseOrderNo;
+
+        orderBO.set("PURCHASE_ORDER_NO", purchaseOrderNo);
+
+        SDK.getBOAPI().update("BO_EU_DNCTT_CONTRACT", orderBO);
+
+
     }
 }

+ 2 - 0
com.awspaas.user.apps.donenow_ivt/src/com/awspaas/user/apps/donenow_ivt/event/ivtOrderProcessAfterComplete.java

@@ -201,6 +201,8 @@ public class ivtOrderProcessAfterComplete extends ExecuteListener {
                         paymentPlan.set("REMAIN_AMOUNT", paymentPlan.get("PLAN_AMOUNT"));
                         paymentPlan.set("CONTRACT_COST_ID", orderProduct.getString("CONTRACT_COST_ID"));
                         paymentPlan.set("CONTRACT_SERVICE_ID", service.getId());
+                        paymentPlan.set("PAY_DESC", orderProduct.getString("NAME"));
+
                         SDK.getBOAPI().create("BO_EU_DNIVT_ORDER_PAYMENT_PLAN", paymentPlan, processInstance, uc);
 
                         System.out.println("==== 创建付款计划:" + paymentPlan.get("PLAN_DATE") + ",金额:" + paymentPlan.get("PLAN_AMOUNT") + " ====");

+ 58 - 0
com.awspaas.user.apps.donenow_ivt/src/com/awspaas/user/apps/donenow_ivt/event/payRequestProcessAfterComplete.java

@@ -0,0 +1,58 @@
+package com.awspaas.user.apps.donenow_ivt.event;
+
+import com.actionsoft.bpms.bo.engine.BO;
+import com.actionsoft.bpms.bpmn.engine.core.delegate.ProcessExecutionContext;
+import com.actionsoft.bpms.bpmn.engine.listener.ExecuteListener;
+import com.actionsoft.sdk.local.SDK;
+import com.actionsoft.sdk.local.api.Logger;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+public class payRequestProcessAfterComplete extends ExecuteListener {
+    public String getDescription() {
+        return "流程结束事件:付款申请审批完成后触发";
+    }
+
+    private static final Logger logger = SDK.getLogAPI().getLogger(payRequestProcessAfterComplete.class);//记录日志
+    private final String[] excludesArray = new String[]{"ID", "ORGID", "BINDID", "CREATEDATE", "CREATEUSER", "UPDATEDATE", "UPDATEUSER"};
+
+    /**
+     *
+     * @param processExecutionContext
+     * @throws Exception
+     */
+    @Override
+    public void execute(ProcessExecutionContext processExecutionContext) throws Exception {
+        String bindid = processExecutionContext.getProcessInstance().getId();
+
+        logger.info("流程结束事件:付款申请审批完成后触发");
+
+        BO main = SDK.getBOAPI().getByProcess("BO_EU_DNIVT_PAY_REQUEST", bindid);
+        List<BO> details = SDK.getBOAPI().query("BO_EU_DNIVT_PAY_REQUEST_DETAIL").addQuery("BINDID =", bindid).list();
+
+        if (details != null && details.size() > 0)
+            for (BO detail : details) {
+                String PAYMENT_PLAN_ID = detail.getString("PAYMENT_PLAN_ID");
+                BigDecimal PLAN_AMOUNT = detail.get("PLAN_AMOUNT", BigDecimal.class);
+
+                BO paymentPlan = SDK.getBOAPI().get("BO_EU_DNIVT_ORDER_PAYMENT_PLAN", PAYMENT_PLAN_ID);
+
+                BigDecimal PLAN_AMOUNT_OLD = paymentPlan.get("PLAN_AMOUNT", BigDecimal.class);
+                BigDecimal PAY_AMOUNT = paymentPlan.get("PAY_AMOUNT", BigDecimal.class);
+
+                PAY_AMOUNT = PAY_AMOUNT.add(PLAN_AMOUNT);
+
+                BigDecimal REMAIN_AMOUNT = PLAN_AMOUNT_OLD.subtract(PAY_AMOUNT);
+                paymentPlan.set("REMAIN_AMOUNT", REMAIN_AMOUNT);
+                paymentPlan.set("PAY_AMOUNT", PAY_AMOUNT);
+                //PAYER、PAY_DATE
+                paymentPlan.set("PAYER", main.get("PAY_DATE"));
+                paymentPlan.set("PAY_DATE", main.get("PAY_USERID"));
+
+                SDK.getBOAPI().update("BO_EU_DNIVT_ORDER_PAYMENT_PLAN", paymentPlan);
+
+            }
+
+    }
+}

+ 69 - 0
com.awspaas.user.apps.donenow_ivt/src/com/awspaas/user/apps/donenow_ivt/utils/CityAbbreviationUtil.java

@@ -0,0 +1,69 @@
+package com.awspaas.user.apps.donenow_ivt.utils;
+
+import net.sourceforge.pinyin4j.PinyinHelper;
+import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType;
+import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;
+import net.sourceforge.pinyin4j.format.HanyuPinyinToneType;
+import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination;
+
+public class CityAbbreviationUtil {
+
+    // 处理城市名称,去除常见后缀(如"市"、"省"等)
+    private static String processCityName(String city) {
+        if (city == null || city.trim().isEmpty()) {
+            return "";
+        }
+        // 定义需要去除的后缀
+        String[] suffixes = {"市", "省", "自治区", "自治州", "地区", "盟", "县", "区"};
+        for (String suffix : suffixes) {
+            if (city.endsWith(suffix)) {
+                return city.substring(0, city.length() - suffix.length());
+            }
+        }
+        return city;
+    }
+
+    // 获取单个汉字的拼音首字母(大写)
+    private static char getFirstLetter(char chineseChar) {
+        HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat();
+        format.setCaseType(HanyuPinyinCaseType.UPPERCASE); // 首字母大写
+        format.setToneType(HanyuPinyinToneType.WITHOUT_TONE); // 不带声调
+
+        try {
+            // 多音字可能返回多个拼音,取第一个
+            String[] pinyinArray = PinyinHelper.toHanyuPinyinStringArray(chineseChar, format);
+            if (pinyinArray != null && pinyinArray.length > 0) {
+                return pinyinArray[0].charAt(0); // 返回首字母
+            }
+        } catch (BadHanyuPinyinOutputFormatCombination e) {
+            e.printStackTrace();
+        }
+        return chineseChar; // 非汉字直接返回原字符
+    }
+
+    // 生成城市拼音首字母缩写
+    public static String getCityAbbreviation(String city) {
+        String processedCity = processCityName(city);
+        if (processedCity.isEmpty()) {
+            return "";
+        }
+
+        StringBuilder abbreviation = new StringBuilder();
+        for (int i = 0; i < processedCity.length(); i++) {
+            char c = processedCity.charAt(i);
+            abbreviation.append(getFirstLetter(c));
+        }
+        return abbreviation.toString();
+    }
+
+    // 测试
+    public static void main(String[] args) {
+        String cssx = "上海市";
+        System.out.println(getCityAbbreviation(cssx)); // 输出:SH
+
+        // 其他测试案例
+        System.out.println(getCityAbbreviation("北京市")); // 输出:BJ
+        System.out.println(getCityAbbreviation("广州市")); // 输出:GZ
+        System.out.println(getCityAbbreviation("四川省")); // 输出:SC
+    }
+}