Veronique 1 anno fa
parent
commit
c4d8a54ad1

+ 27 - 0
conf/KeyId.xml

@@ -190,4 +190,31 @@
             <TableWhere/>
         </Table>
     </Item>
+
+    <Item>
+        <IDName>deDesignTagType.id</IDName>
+        <Table>
+            <TableName>deDesignTagType</TableName>
+            <IDFieldName>id</IDFieldName>
+            <TableWhere/>
+        </Table>
+    </Item>
+
+    <Item>
+        <IDName>deDesignTag.id</IDName>
+        <Table>
+            <TableName>deDesignTag</TableName>
+            <IDFieldName>id</IDFieldName>
+            <TableWhere/>
+        </Table>
+    </Item>
+
+    <Item>
+        <IDName>deTemplateTag.id</IDName>
+        <Table>
+            <TableName>deTemplateTag</TableName>
+            <IDFieldName>id</IDFieldName>
+            <TableWhere/>
+        </Table>
+    </Item>
 </Items>

+ 54 - 0
conf/sqlUpdate_back/2024-12-30.sql

@@ -0,0 +1,54 @@
+drop table if exists deDesignTagType1000;
+create table deDesignTagType1000(
+                                    id	bigint  default 0,
+                                    idParentType	bigint  default 0,
+                                    name	varchar(50) default '',
+                                    createBy	bigint  default 0,
+                                    createTime	datetime default NOW(),
+                                    createTimeLong	bigint  default 0,
+                                    updateBy	bigint  default 0,
+                                    updateTime	datetime default NOW(),
+                                    updateTimeLong	bigint  default 0,
+                                    primary key (id)
+)
+    ENGINE = INNODB
+AUTO_INCREMENT = 1
+DEFAULT CHARSET = utf8
+COMMENT = '';
+
+drop table if exists deDesignTag1000;
+create table deDesignTag1000(
+                                id	bigint  default 0,
+                                idType	bigint  default 0,
+                                tagName	varchar(50) default '',
+                                createBy	bigint  default 0,
+                                createTime	datetime default NOW(),
+                                createTimeLong	bigint  default 0,
+                                updateBy	bigint  default 0,
+                                updateTime	datetime default NOW(),
+                                updateTimeLong	bigint  default 0,
+                                primary key (id)
+)
+    ENGINE = INNODB
+AUTO_INCREMENT = 1
+DEFAULT CHARSET = utf8
+COMMENT = '';
+
+drop table if exists deTemplateTag1000;
+create table deTemplateTag1000(
+                                  id	bigint  default 0,
+                                  idTemplate	bigint  default 0,
+                                  tagName	varchar(50) default '',
+                                  tagTypeName	varchar(50) default '',
+                                  createBy	bigint  default 0,
+                                  createTime	datetime default NOW(),
+                                  createTimeLong	bigint  default 0,
+                                  updateBy	bigint  default 0,
+                                  updateTime	datetime default NOW(),
+                                  updateTimeLong	bigint  default 0,
+                                  primary key (id)
+)
+    ENGINE = INNODB
+AUTO_INCREMENT = 1
+DEFAULT CHARSET = utf8
+COMMENT = '';

+ 100 - 7
conf/sqlroot/com/sdtool/business/dao/DesignDao.dql

@@ -18,23 +18,33 @@ updateTime = #{updatetime}
 where id = #{id};
 
 -- [selectDesignTemplates]
-select *
-from $table$
+select a.*
+from $table1$ a left join $table2$ b on a.id = b.idTemplate
 -- trim prefix=WHERE prefixOverrides=AND|OR
   -- isNotEmpty voidFlag
     -- if voidFlag >= 0
-        voidFlag = #{voidFlag}
+        a.voidFlag = #{voidFlag}
     -- end
   -- end
   -- isNotEmpty keyWord
-    and (templateName LIKE #{Like:keyWord})
+    and (a.templateName LIKE #{Like:keyWord})
   -- end
   -- isNotEmpty templateName
-    and templateName LIKE #{Like:templateName}
+    and a.templateName LIKE #{Like:templateName}
+  -- end
+  -- isNotEmpty productIdentity
+      and FIND_IN_SET(#{productIdentity},a.productIdentity)
   -- end
+  -- isNotEmpty tags
+      and b.tagName in (/* in tags */)
+  -- end
+-- end
+GROUP BY a.id
+-- isNotEmpty tags
+HAVING COUNT(DISTINCT b.tagName) = #{tagCount}
 -- end
 -- isEmpty orderBy
-order by createTime desc
+order by a.createTime desc
 -- else
 order by #{orderBy}
 -- end
@@ -87,6 +97,7 @@ updateTimeLong ) values ( #{id}, #{templatename}, #{backgroundpath}, #{viewthumb
 
 -- [updateDesignTemplate]
 update $table$ set templateName = #{templatename},
+productIdentity = #{productidentity},
 jsonContent = #{jsoncontent},
 backgroundPath = #{backgroundpath},
 canvasHeight = #{canvasheight},
@@ -166,4 +177,86 @@ update $table$ set pdfDownloadUrl = #{pdfdownloadurl}
 where id = #{id};
 
 -- [deleteDesignOrderItem]
-delete from $table$ where idOrder = #{id};
+delete from $table$ where idOrder = #{id};
+
+-- [queryDesignTagType]
+select *
+from $table$
+-- trim prefix=WHERE prefixOverrides=AND|OR
+  -- isNotEmpty keyWord
+     (name LIKE #{Like:keyWord})
+  -- end
+  -- isNotEmpty ids
+     and id in (/* in ids */)
+  -- end
+-- end
+-- isEmpty orderBy
+order by createTime desc
+-- else
+order by #{orderBy}
+-- end
+;
+
+-- [getDesignTagType]
+select * from $table$ where id = #{id};
+
+-- [newDesignTagType]
+insert into $table$ (id, idParentType, name, createBy,
+createTime, createTimeLong, updateBy,
+updateTime, updateTimeLong ) values ( #{id}, #{idparenttype}, #{name}, #{createby},
+#{createtime}, #{createtimelong}, #{updateby},
+#{updatetime}, #{updatetimelong} );
+
+-- [deleteDesignTagType]
+delete from $table$ where id = #{id};
+
+-- [updateDesignTagType]
+update $table$ set idParentType = #{idparenttype},name = #{name},createBy = #{createby},createTime = #{createtime},
+createTimeLong = #{createtimelong},updateBy = #{updateby},updateTime = #{updatetime},updateTimeLong = #{updatetimelong}
+ where id = #{id};
+
+-- [queryDesignTags]
+select *
+from $table$
+-- trim prefix=WHERE prefixOverrides=AND|OR
+  -- isNotEmpty keyWord
+     (tagName LIKE #{Like:keyWord})
+  -- end
+  -- isNotEmpty idType
+    -- if idType >= 0
+      and idType = #{idType}
+    -- end
+  -- end
+-- end
+-- isEmpty orderBy
+order by createTime desc
+-- else
+order by #{orderBy}
+-- end
+;
+
+-- [newDesignTag]
+insert into $table$ (id, idType, tagName, createBy,
+createTime, createTimeLong, updateBy,
+updateTime, updateTimeLong ) values ( #{id}, #{idtype}, #{tagname}, #{createby},
+#{createtime}, #{createtimelong}, #{updateby},
+#{updatetime}, #{updatetimelong} );
+
+-- [changeTagType]
+update $table$ set idType = #{idtype} where id = #{id};
+
+-- [deleteDesignTag]
+delete from $table$ where id = #{id};
+
+-- [getTemplateTags]
+select * from $table$ where idTemplate in (/* in ids */);
+
+-- [deleteTemplateTag]
+delete from $table$ where idTemplate = #{idTemplate};
+
+-- [addTemplateTag]
+insert into $table$ (id, idTemplate, tagName, tagTypeName,
+createBy, createTime, createTimeLong,
+updateBy, updateTime, updateTimeLong ) values ( #{id}, #{idtemplate}, #{tagname}, #{tagtypename},
+#{createby}, #{createtime}, #{createtimelong},
+#{updateby}, #{updatetime}, #{updatetimelong} );

BIN
doc/设计站技术手册.docx


+ 75 - 3
sdBusiness/src/main/java/com/sdtool/business/dao/DesignDao.java

@@ -29,9 +29,9 @@ public interface DesignDao extends DaoRepository {
     //region 设计模板
     @Sharding(databaseShardingStrategy = SupplierDataBaseShardingStrategy.class, tableShardingStrategy = SupplierTableShardingStrategy.class)
     @DAOMethod(operator = OperatorType.QUERY, owait = OperatorWait.AWAIT)
-    @SqlId(clazz = DesignDao.class, sql = "selectDesignTemplates", table = "dedesigntemplate", params = {1})
+    @SqlId(clazz = DesignDao.class, sql = "selectDesignTemplates", table = "dedesigntemplate,detemplatetag", params = {1})
     List<DesignTemplate> selectDesignTemplates(RMap params, @DatabaseShardingBy String dataSourceId, @TableShardingBy Long supplierCode,
-                                              PageFlipper pageFlipper);
+                                               PageFlipper pageFlipper);
 
     @Sharding(databaseShardingStrategy = SupplierDataBaseShardingStrategy.class, tableShardingStrategy = SupplierTableShardingStrategy.class)
     @DAOMethod(operator = OperatorType.QUERY, owait = OperatorWait.AWAIT)
@@ -67,7 +67,7 @@ public interface DesignDao extends DaoRepository {
     @DAOMethod(operator = OperatorType.QUERY, owait = OperatorWait.AWAIT)
     @SqlId(clazz = DesignDao.class, sql = "selectDesignOrders", table = "dedesignorder", params = {1})
     List<DesignOrder> selectDesignOrders(RMap params, @DatabaseShardingBy String dataSourceId, @TableShardingBy Long supplierCode,
-                                            PageFlipper pageFlipper);
+                                         PageFlipper pageFlipper);
 
     @Sharding(databaseShardingStrategy = SupplierDataBaseShardingStrategy.class, tableShardingStrategy = SupplierTableShardingStrategy.class)
     @DAOMethod(operator = OperatorType.QUERY, owait = OperatorWait.AWAIT)
@@ -93,4 +93,76 @@ public interface DesignDao extends DaoRepository {
     void pdfCallbackDesignOrder(DesignOrder designOrder, @DatabaseShardingBy String dataSourceId, @TableShardingBy Long supplierCode);
     //endregion
 
+    //region 模板标签档案
+    @Sharding(databaseShardingStrategy = SupplierDataBaseShardingStrategy.class, tableShardingStrategy = SupplierTableShardingStrategy.class)
+    @DAOMethod(operator = OperatorType.QUERY, owait = OperatorWait.AWAIT)
+    @SqlId(clazz = DesignDao.class, sql = "queryDesignTagType", table = "deDesignTagType", params = {1})
+    List<DesignTagType> queryDesignTagType(RMap params, @DatabaseShardingBy String dataSourceId, @TableShardingBy Long supplierCode);
+
+    @Sharding(databaseShardingStrategy = SupplierDataBaseShardingStrategy.class, tableShardingStrategy = SupplierTableShardingStrategy.class)
+    @DAOMethod(operator = OperatorType.QUERY, owait = OperatorWait.AWAIT)
+    @SqlId(clazz = DesignDao.class, sql = "queryDesignTagType", table = "deDesignTagType", params = {1})
+    List<DesignTagType> queryDesignTagType(RMap params, @DatabaseShardingBy String dataSourceId, @TableShardingBy Long supplierCode, PageFlipper pageFlipper);
+
+    @Sharding(databaseShardingStrategy = SupplierDataBaseShardingStrategy.class, tableShardingStrategy = SupplierTableShardingStrategy.class)
+    @DAOMethod(operator = OperatorType.QUERY, owait = OperatorWait.AWAIT)
+    @SqlId(clazz = DesignDao.class, sql = "getDesignTagType", table = "deDesignTagType", params = {1}, sort = 1)
+    DesignTagType getDesignTagType(RMap params, @DatabaseShardingBy String dataSourceId, @TableShardingBy Long supplierCode);
+
+    @Sharding(databaseShardingStrategy = SupplierDataBaseShardingStrategy.class, tableShardingStrategy = SupplierTableShardingStrategy.class)
+    @DAOMethod(operator = OperatorType.UPDATE, owait = OperatorWait.ASNYC)
+    @SqlId(clazz = DesignDao.class, sql = "newDesignTagType", table = "deDesignTagType", params = {1}, sort = 1)
+    void newDesignTagType(DesignTagType designTagType, @DatabaseShardingBy String dataSourceId, @TableShardingBy Long supplierCode);
+
+    @Sharding(databaseShardingStrategy = SupplierDataBaseShardingStrategy.class, tableShardingStrategy = SupplierTableShardingStrategy.class)
+    @DAOMethod(operator = OperatorType.UPDATE, owait = OperatorWait.ASNYC)
+    @SqlId(clazz = DesignDao.class, sql = "deleteDesignTagType", table = "deDesignTagType", params = {1}, sort = 1)
+    @SqlId(clazz = DesignDao.class, sql = "changeTagType", table = "deDesignTag", params = {2}, sort = 2)
+    void deleteDesignTagType(List<DesignTagType> designTagTypes, List<DesignTag> tagList, @DatabaseShardingBy String dataSourceId, @TableShardingBy Long supplierCode);
+
+    @Sharding(databaseShardingStrategy = SupplierDataBaseShardingStrategy.class, tableShardingStrategy = SupplierTableShardingStrategy.class)
+    @DAOMethod(operator = OperatorType.UPDATE, owait = OperatorWait.ASNYC)
+    @SqlId(clazz = DesignDao.class, sql = "updateDesignTagType", table = "deDesignTagType", params = {1}, sort = 1)
+    void updateDesignTagType(DesignTagType designTagType, @DatabaseShardingBy String dataSourceId, @TableShardingBy Long supplierCode);
+
+    @Sharding(databaseShardingStrategy = SupplierDataBaseShardingStrategy.class, tableShardingStrategy = SupplierTableShardingStrategy.class)
+    @DAOMethod(operator = OperatorType.QUERY, owait = OperatorWait.AWAIT)
+    @SqlId(clazz = DesignDao.class, sql = "queryDesignTags", table = "deDesignTag", params = {1})
+    List<DesignTag> queryDesignTags(RMap params, @DatabaseShardingBy String dataSourceId, @TableShardingBy Long supplierCode,
+                                    PageFlipper pageFlipper);
+
+    @Sharding(databaseShardingStrategy = SupplierDataBaseShardingStrategy.class, tableShardingStrategy = SupplierTableShardingStrategy.class)
+    @DAOMethod(operator = OperatorType.QUERY, owait = OperatorWait.AWAIT)
+    @SqlId(clazz = DesignDao.class, sql = "queryDesignTags", table = "deDesignTag", params = {1})
+    List<DesignTag> queryDesignTags(RMap params, @DatabaseShardingBy String dataSourceId, @TableShardingBy Long supplierCode);
+
+    @Sharding(databaseShardingStrategy = SupplierDataBaseShardingStrategy.class, tableShardingStrategy = SupplierTableShardingStrategy.class)
+    @DAOMethod(operator = OperatorType.UPDATE, owait = OperatorWait.ASNYC)
+    @SqlId(clazz = DesignDao.class, sql = "newDesignTag", table = "deDesignTag", params = {1}, sort = 1)
+    void newDesignTag(DesignTag designTag, @DatabaseShardingBy String dataSourceId, @TableShardingBy Long supplierCode);
+
+    @Sharding(databaseShardingStrategy = SupplierDataBaseShardingStrategy.class, tableShardingStrategy = SupplierTableShardingStrategy.class)
+    @DAOMethod(operator = OperatorType.UPDATE, owait = OperatorWait.ASNYC)
+    @SqlId(clazz = DesignDao.class, sql = "changeTagType", table = "deDesignTag", params = {1}, sort = 1)
+    void changeTagType(List<DesignTag> tagList, @DatabaseShardingBy String dataSourceId, @TableShardingBy Long supplierCode);
+
+    @Sharding(databaseShardingStrategy = SupplierDataBaseShardingStrategy.class, tableShardingStrategy = SupplierTableShardingStrategy.class)
+    @DAOMethod(operator = OperatorType.UPDATE, owait = OperatorWait.ASNYC)
+    @SqlId(clazz = DesignDao.class, sql = "deleteDesignTag", table = "deDesignTag", params = {1}, sort = 1)
+    void deleteDesignTag(DesignTag designTag, @DatabaseShardingBy String dataSourceId, @TableShardingBy Long supplierCode);
+    //endregion
+
+    //region 模板标签
+    @Sharding(databaseShardingStrategy = SupplierDataBaseShardingStrategy.class, tableShardingStrategy = SupplierTableShardingStrategy.class)
+    @DAOMethod(operator = OperatorType.QUERY, owait = OperatorWait.AWAIT)
+    @SqlId(clazz = DesignDao.class, sql = "getTemplateTags", table = "deTemplateTag", params = {1})
+    List<TemplateTag> getTemplateTags(RMap params, @DatabaseShardingBy String dataSourceId, @TableShardingBy Long supplierCode);
+
+    @Sharding(databaseShardingStrategy = SupplierDataBaseShardingStrategy.class, tableShardingStrategy = SupplierTableShardingStrategy.class)
+    @DAOMethod(operator = OperatorType.UPDATE, owait = OperatorWait.ASNYC)
+    @SqlId(clazz = DesignDao.class, sql = "deleteTemplateTag", table = "deTemplateTag", params = {1}, sort = 1)
+    @SqlId(clazz = DesignDao.class, sql = "addTemplateTag", table = "deTemplateTag", params = {2}, sort = 2)
+    void modifyTemplateTags(RMap params, List<TemplateTag> tagList, @DatabaseShardingBy String dataSourceId, @TableShardingBy Long supplierCode);
+    //endregion
+
 }

+ 265 - 1
sdBusiness/src/main/java/com/sdtool/business/service/mall/DesignServiceImpl.java

@@ -49,6 +49,7 @@ import java.util.*;
 import java.util.List;
 import java.util.concurrent.ScheduledThreadPoolExecutor;
 import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
 
 @Local
 @AutoLoad(false)
@@ -154,6 +155,19 @@ public class DesignServiceImpl extends BaseService implements DesignService {
             throw new RuntimeException(e);
         }
 
+        //如果是windows系统,把字体拷到c:\windows\fonts目录
+        //需求administrator权限
+        String os = System.getProperty("os.name").toLowerCase();
+        if (os.contains("win")) {
+            try {
+                Path srcPath = Paths.get(fontUrl);
+                Files.copy(srcPath, Paths.get("C:\\Windows\\Fonts\\" + srcPath.getFileName()));
+            } catch (IOException e) {
+//                throw new RuntimeException(e);
+                logger.error("安装系统字体失败: " + e.getMessage());
+            }
+        }
+
         designFont.setVoidFlag(0);
         DesignFont.create(designFont, currentUser.getId());
 
@@ -181,9 +195,28 @@ public class DesignServiceImpl extends BaseService implements DesignService {
 
     @Override
     public RetResult<List<DesignTemplate>> queryDesignTemplates(RMap params, PageFlipper pageFlipper, String dataSourceId, long supplierCode) {
+        if (ERPUtils.mapContainKey(params, "tags")) {
+            List tags = params.getList("tags");
+            if (tags.size() > 0) {
+                params.put("tagCount", params.getList("tags").size());
+                params.put("tags", tags.stream().map(tag -> "'" + tag + "'").collect(Collectors.toList()));
+            }
+        }
         List<DesignTemplate> templateList = designDao.selectDesignTemplates(params, dataSourceId, supplierCode, pageFlipper);
 
-        templateList.forEach(x -> x.setJsonContent(""));
+        //获取标签
+        List<TemplateTag> allTags = new ArrayList<>();
+        if (templateList.size() > 0) {
+            List<Long> idTemplates = templateList.stream().map(DesignTemplate::getId).toList();
+            RMap rMap = new RMap();
+            rMap.put("ids", idTemplates);
+            allTags.addAll(designDao.getTemplateTags(rMap, dataSourceId, supplierCode));
+        }
+
+        templateList.forEach(x -> {
+            x.setJsonContent("");
+            x.setTagList(allTags.stream().filter(y -> y.getIdTemplate() == x.getId()).collect(Collectors.toList()));
+        });
         return RetResult.<List<DesignTemplate>>successT().result(templateList).page(pageFlipper);
     }
 
@@ -278,6 +311,12 @@ public class DesignServiceImpl extends BaseService implements DesignService {
                 throw new RuntimeException(e);
             }
 
+            //标签信息
+            RMap rMap = new RMap();
+            rMap.put("ids", new Long[]{id});
+            List<TemplateTag> tags = designDao.getTemplateTags(rMap, dataSourceId, supplierCode);
+            redisTemplate.setTagList(tags);
+
             fillParamsToTemplate(redisTemplate, params);
             return RetResult.<DesignTemplate>successT().result(redisTemplate);
         }
@@ -757,4 +796,229 @@ public class DesignServiceImpl extends BaseService implements DesignService {
     }
 
     //endregion
+
+
+    //region 模板标签档案
+
+
+    @Override
+    public RetResult<List<DesignTagType>> queryDesignTagTypeFlatten(RMap params, String dataSourceId, long supplierCode, PageFlipper pageFlipper) {
+        List<DesignTagType> typeList = designDao.queryDesignTagType(params, dataSourceId, supplierCode, pageFlipper);
+        return RetResult.<List<DesignTagType>>successT().result(typeList).page(pageFlipper);
+    }
+
+
+    private void buildTypeTree(List<DesignTagType> designTagTypes, DesignTagType parentType) {
+        List<DesignTagType> childrenTypes = designTagTypes.stream().filter(x -> x.getIdParentType() == parentType.getId()).findAny().stream().toList();
+        parentType.setSubTypes(childrenTypes);
+
+        childrenTypes.forEach(designTagType -> {
+            buildTypeTree(designTagTypes, designTagType);
+        });
+    }
+
+    @Override
+    public RetResult<List<DesignTagType>> queryDesignTagType(String dataSourceId, long supplierCode) {
+        List<DesignTagType> typeList = designDao.queryDesignTagType(new RMap(), dataSourceId, supplierCode);
+        //手动创建一个未分组
+        DesignTagType unGroupedType = new DesignTagType();
+        unGroupedType.setIdParentType(0);
+        unGroupedType.setId(0);
+        unGroupedType.setName("未分组");
+        typeList.add(unGroupedType);
+
+
+        execPageFlipper(1000, (pageFlipper) -> {
+            List<DesignTag> tagList = designDao.queryDesignTags(new RMap(), dataSourceId, supplierCode, pageFlipper);
+            Map<Long, List<DesignTag>> groupTags = tagList.stream().collect(Collectors.groupingBy(DesignTag::getIdType));
+
+            groupTags.forEach((k, v) -> {
+                typeList.stream().filter(x -> x.getId() == k).findFirst().ifPresent(x -> x.getTags().addAll(v));
+            });
+        });
+
+        //先自行找到root
+        List<DesignTagType> roots = typeList.stream().filter(x -> x.getIdParentType() == 0).findAny().stream().toList();
+        roots.forEach(designTagType -> {
+            buildTypeTree(typeList, designTagType);
+        });
+
+        return RetResult.<List<DesignTagType>>successT().result(roots);
+    }
+
+    @Override
+    public RetResult<DesignTagType> getDesignTagType(long idTagType, String dataSourceId, long supplierCode, ERPTokenUser currentUser) {
+        RMap params = new RMap();
+        params.put("id", idTagType);
+
+        DesignTagType designTagType = designDao.getDesignTagType(params, dataSourceId, supplierCode);
+        if (designTagType == null) return RetResult.<DesignTagType>errorT().retinfo("查找的信息不存在");
+
+        return RetResult.<DesignTagType>successT().result(designTagType);
+    }
+
+    @Override
+    public RetResult<DesignTagType> newDesignTagType(DesignTagType tagType, String dataSourceId, long supplierCode, ERPTokenUser currentUser) {
+        tagType.setId(tableIdService.getTableIdMulti("deDesignTagType.id", 1, dataSourceId, String.valueOf(supplierCode)));
+        DesignTagType.create(tagType, currentUser.getId());
+
+        designDao.newDesignTagType(tagType, dataSourceId, supplierCode);
+
+        return RetResult.<DesignTagType>successT().result(tagType);
+    }
+
+    private List<DesignTag> collectDesignTags(DesignTagType type) {
+        List<DesignTag> tagList = type.getTags();
+        type.getSubTypes().forEach(x -> {
+            tagList.addAll(collectDesignTags(x));
+        });
+
+        return tagList;
+    }
+
+    private List<DesignTagType> collectDesignTypes(DesignTagType type) {
+        List<DesignTagType> typeList = type.getSubTypes();
+        typeList.forEach(x -> {
+            typeList.addAll(collectDesignTypes(x));
+        });
+
+        return typeList;
+    }
+
+
+    //删除类别,则该类别下所有的tag置为未分组
+    @Override
+    public RetResult<DesignTagType> deleteDesignTagType(long id, String dataSourceId, long supplierCode, ERPTokenUser currentUser) {
+        List<DesignTagType> typeList = designDao.queryDesignTagType(new RMap(), dataSourceId, supplierCode);
+
+        execPageFlipper(1000, (pageFlipper) -> {
+            List<DesignTag> tagList = designDao.queryDesignTags(new RMap(), dataSourceId, supplierCode, pageFlipper);
+            Map<Long, List<DesignTag>> groupTags = tagList.stream().collect(Collectors.groupingBy(DesignTag::getIdType));
+
+            groupTags.forEach((k, v) -> {
+                typeList.stream().filter(x -> x.getId() == k).findFirst().ifPresent(x -> x.getTags().addAll(v));
+            });
+        });
+
+        DesignTagType toDeleteType = typeList.stream().filter(x -> x.getId() == id).findFirst().orElse(null);
+
+        if (toDeleteType != null) {
+            List<DesignTag> changeTagList = collectDesignTags(toDeleteType);
+            changeTagList.forEach(x -> {
+                x.setIdType(0);
+            });
+
+            List<DesignTagType> toDeleteTypeList = collectDesignTypes(toDeleteType);
+            toDeleteTypeList.add(toDeleteType);
+
+            designDao.deleteDesignTagType(toDeleteTypeList, changeTagList, dataSourceId, supplierCode);
+        }
+        return RetResult.successT();
+    }
+
+    @Override
+    public RetResult<DesignTagType> deleteDesignTagTypeFlatten(long id, String dataSourceId, long supplierCode, ERPTokenUser currentUser) {
+        RMap params = new RMap();
+        params.put("idType", id);
+
+
+        List<DesignTag> tagList = designDao.queryDesignTags(params, dataSourceId, supplierCode);
+        tagList.forEach(x -> {
+            x.setIdType(0);
+        });
+
+        List<DesignTagType> toDeleteList = new ArrayList<>();
+        DesignTagType toDeleteType = new DesignTagType();
+        toDeleteType.setId(id);
+        toDeleteList.add(toDeleteType);
+
+        designDao.deleteDesignTagType(toDeleteList, tagList, dataSourceId, supplierCode);
+        return RetResult.successT();
+    }
+
+    @Override
+    public RetResult<DesignTagType> updateDesignTagType(DesignTagType tagType, String dataSourceId, long supplierCode, ERPTokenUser currentUser) {
+        DesignTagType.update(tagType, currentUser.getId());
+        designDao.updateDesignTagType(tagType, dataSourceId, supplierCode);
+
+        return RetResult.successT();
+    }
+
+    @Override
+    public RetResult<List<DesignTag>> queryDesignTags(RMap params, String dataSourceId, long supplierCode, PageFlipper pageFlipper) {
+        List<DesignTag> designTags = designDao.queryDesignTags(params, dataSourceId, supplierCode, pageFlipper);
+        return RetResult.<List<DesignTag>>successT().result(designTags).page(pageFlipper);
+    }
+
+    @Override
+    public RetResult<DesignTag> newDesignTag(DesignTag designTag, String dataSourceId, long supplierCode, ERPTokenUser currentUser) {
+        designTag.setId(tableIdService.getTableIdMulti("deDesignTag.id", 1, dataSourceId, String.valueOf(supplierCode)));
+        DesignTag.create(designTag, currentUser.getId());
+
+        designDao.newDesignTag(designTag, dataSourceId, supplierCode);
+        return RetResult.<DesignTag>successT().result(designTag);
+    }
+
+    @Override
+    public RetResult<List<DesignTag>> changeTagType(List<DesignTag> tagList, String dataSourceId, long supplierCode, ERPTokenUser currentUser) {
+        tagList.forEach(x -> {
+            DesignTag.update(x, currentUser.getId());
+        });
+
+        designDao.changeTagType(tagList, dataSourceId, supplierCode);
+        return RetResult.successT();
+    }
+
+    @Override
+    public RetResult<DesignTag> deleteDesignTag(long id, String dataSourceId, long supplierCode, ERPTokenUser currentUser) {
+        DesignTag designTag = new DesignTag();
+        designTag.setId(id);
+
+        designDao.deleteDesignTag(designTag, dataSourceId, supplierCode);
+        return RetResult.successT();
+    }
+    //endregion
+
+    //region 模板标签
+    @Override
+    public RetResult<List<TemplateTag>> getTemplateTags(long idTemplate, String dataSourceId, long supplierCode) {
+        RMap params = new RMap();
+        params.put("ids", new Long[]{idTemplate});
+        List<TemplateTag> tags = designDao.getTemplateTags(params, dataSourceId, supplierCode);
+        return RetResult.<List<TemplateTag>>successT().result(tags);
+    }
+
+    @Override
+    public RetResult<List<TemplateTag>> modifyTemplateTags(long idTemplate, List<DesignTag> tags, String dataSourceId, long supplierCode, ERPTokenUser currentUser) {
+        RMap params = new RMap();
+        params.put("idTemplate", idTemplate);
+
+        List<Long> ids = tags.stream().map(DesignTag::getIdType).filter(idType -> idType > 0).toList();
+        RMap searchParams = new RMap();
+        searchParams.put("ids", ids);
+        List<DesignTagType> typeList = designDao.queryDesignTagType(searchParams, dataSourceId, supplierCode);
+
+        long idTemplateTag = tableIdService.getTableIdMulti("deTemplateTag.id", tags.size(), dataSourceId, String.valueOf(supplierCode));
+        List<TemplateTag> templateTags = new ArrayList<>();
+        for (DesignTag x : tags) {
+            DesignTagType type = typeList.stream().filter(y -> y.getId() == x.getIdType()).findFirst().orElse(null);
+            TemplateTag templateTag = new TemplateTag();
+            templateTag.setId(idTemplateTag++);
+            templateTag.setIdTemplate(idTemplate);
+            templateTag.setTagName(x.getTagName());
+            if (type != null)
+                templateTag.setTagTypeName(type.getName());
+            else {
+                if (StringUtils.isBlank(x.getTagTypeName()))
+                    templateTag.setTagTypeName("未分组");
+                else templateTag.setTagTypeName(x.getTagTypeName());
+            }
+            TemplateTag.create(templateTag, currentUser.getId());
+            templateTags.add(templateTag);
+        }
+
+        designDao.modifyTemplateTags(params, templateTags, dataSourceId, supplierCode);
+        return RetResult.successT();
+    }
+    //endregion
 }

+ 33 - 3
sdCommon/src/main/java/com/sdtool/common/api/mall/DesignService.java

@@ -3,9 +3,7 @@ package com.sdtool.common.api.mall;
 import com.sdtool.common.api.ScriptService;
 import com.sdtool.common.entity.base.ProcessIdItem;
 import com.sdtool.common.entity.base.ProcessStringItem;
-import com.sdtool.common.entity.design.DesignFont;
-import com.sdtool.common.entity.design.DesignOrder;
-import com.sdtool.common.entity.design.DesignTemplate;
+import com.sdtool.common.entity.design.*;
 import com.sdtool.common.entity.site.ERPTokenUser;
 import com.sweetfish.service.RetResult;
 import com.sweetfish.source.PageFlipper;
@@ -61,5 +59,37 @@ public interface DesignService extends ScriptService {
     RetResult<DesignOrder> updateDesignOrder(DesignOrder designOrder, String dataSourceId, long supplierCode, ERPTokenUser currentUser);
     //endregion
 
+    //region 模板标签档案
+    //一开始先做扁平化的把,没必要type还有父级结构
+    RetResult<List<DesignTagType>> queryDesignTagTypeFlatten(RMap params, String dataSourceId, long supplierCode, PageFlipper pageFlipper);
+
+
+    RetResult<List<DesignTagType>> queryDesignTagType( String dataSourceId, long supplierCode);
+
+    RetResult<DesignTagType> getDesignTagType(long idTagType, String dataSourceId, long supplierCode, ERPTokenUser currentUser);
+
+    RetResult<DesignTagType> newDesignTagType(DesignTagType tagType, String dataSourceId, long supplierCode, ERPTokenUser currentUser);
+
+    RetResult<DesignTagType> deleteDesignTagType(long id, String dataSourceId, long supplierCode, ERPTokenUser currentUser);
+
+    RetResult<DesignTagType> deleteDesignTagTypeFlatten(long id, String dataSourceId, long supplierCode, ERPTokenUser currentUser);
+
+    RetResult<DesignTagType> updateDesignTagType(DesignTagType tagType, String dataSourceId, long supplierCode, ERPTokenUser currentUser);
+
+
+    RetResult<List<DesignTag>> queryDesignTags(RMap params, String dataSourceId, long supplierCode, PageFlipper pageFlipper);
+
+    RetResult<DesignTag> newDesignTag(DesignTag designTag, String dataSourceId, long supplierCode, ERPTokenUser currentUser);
+
+    RetResult<List<DesignTag>> changeTagType(List<DesignTag> tagList, String dataSourceId, long supplierCode, ERPTokenUser currentUser);
+
+    RetResult<DesignTag> deleteDesignTag(long id, String dataSourceId, long supplierCode, ERPTokenUser currentUser);
+    //endregion
+
+    //region 模板标签
+    RetResult<List<TemplateTag>> getTemplateTags(long idTemplate, String dataSourceId, long supplierCode);
+
+    RetResult<List<TemplateTag>> modifyTemplateTags(long idTemplate, List<DesignTag> tags, String dataSourceId, long supplierCode, ERPTokenUser currentUser);
+    //endregion
 
 }

+ 54 - 0
sdCommon/src/main/java/com/sdtool/common/entity/design/DesignTag.java

@@ -0,0 +1,54 @@
+package com.sdtool.common.entity.design;
+
+import com.sdtool.common.entity.base.BaseEntity;
+import com.sweetfish.util.Comment;
+import org.rex.db.RColumn;
+
+public class DesignTag extends BaseEntity {
+    @Comment("")
+    @RColumn("id")
+    private long id;
+
+    @Comment("")
+    @RColumn("idtype")
+    private long idType;
+
+    @Comment("")
+    @RColumn("tagname")
+    private String tagName;
+
+    @Comment("该字段不写库,传递数据用")
+    private String tagTypeName;
+
+    public long getId() {
+        return id;
+    }
+
+    public void setId(long id) {
+        this.id = id;
+    }
+
+    public long getIdType() {
+        return idType;
+    }
+
+    public void setIdType(long idType) {
+        this.idType = idType;
+    }
+
+    public String getTagName() {
+        return tagName;
+    }
+
+    public void setTagName(String tagName) {
+        this.tagName = tagName;
+    }
+
+    public String getTagTypeName() {
+        return tagTypeName;
+    }
+
+    public void setTagTypeName(String tagTypeName) {
+        this.tagTypeName = tagTypeName;
+    }
+}

+ 65 - 0
sdCommon/src/main/java/com/sdtool/common/entity/design/DesignTagType.java

@@ -0,0 +1,65 @@
+package com.sdtool.common.entity.design;
+
+import com.sdtool.common.entity.base.BaseEntity;
+import com.sweetfish.util.Comment;
+import org.rex.db.RColumn;
+
+import java.util.List;
+
+public class DesignTagType extends BaseEntity {
+    @Comment("")
+    @RColumn("id")
+    private long id;
+
+    @Comment("")
+    @RColumn("idparenttype")
+    private long idParentType;
+
+    @Comment("")
+    @RColumn("name")
+    private String name;
+
+    private List<DesignTagType> subTypes;
+
+    private List<DesignTag> tags;
+
+    public long getId() {
+        return id;
+    }
+
+    public void setId(long id) {
+        this.id = id;
+    }
+
+    public long getIdParentType() {
+        return idParentType;
+    }
+
+    public void setIdParentType(long idParentType) {
+        this.idParentType = idParentType;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public List<DesignTagType> getSubTypes() {
+        return subTypes;
+    }
+
+    public void setSubTypes(List<DesignTagType> subTypes) {
+        this.subTypes = subTypes;
+    }
+
+    public List<DesignTag> getTags() {
+        return tags;
+    }
+
+    public void setTags(List<DesignTag> tags) {
+        this.tags = tags;
+    }
+}

+ 11 - 0
sdCommon/src/main/java/com/sdtool/common/entity/design/DesignTemplate.java

@@ -58,6 +58,9 @@ public class DesignTemplate extends BaseEntity {
     @Comment("元素")
     private List<DesignTemplateItem> itemList = new ArrayList<>();
 
+    @Comment("模板标签")
+    private List<TemplateTag> tagList = new ArrayList<>();
+
     public long getId() {
         return id;
     }
@@ -153,4 +156,12 @@ public class DesignTemplate extends BaseEntity {
     public void setJsonContent(String jsonContent) {
         this.jsonContent = jsonContent;
     }
+
+    public List<TemplateTag> getTagList() {
+        return tagList;
+    }
+
+    public void setTagList(List<TemplateTag> tagList) {
+        this.tagList = tagList;
+    }
 }

+ 55 - 0
sdCommon/src/main/java/com/sdtool/common/entity/design/TemplateTag.java

@@ -0,0 +1,55 @@
+package com.sdtool.common.entity.design;
+
+import com.sdtool.common.entity.base.BaseEntity;
+import com.sweetfish.util.Comment;
+import org.rex.db.RColumn;
+
+public class TemplateTag extends BaseEntity {
+    @Comment("")
+    @RColumn("id")
+    private long id;
+
+    @Comment("")
+    @RColumn("idtemplate")
+    private long idTemplate;
+
+    @Comment("")
+    @RColumn("tagname")
+    private String tagName;
+
+    @Comment("")
+    @RColumn("tagtypename")
+    private String tagTypeName;
+
+    public long getId() {
+        return id;
+    }
+
+    public void setId(long id) {
+        this.id = id;
+    }
+
+    public long getIdTemplate() {
+        return idTemplate;
+    }
+
+    public void setIdTemplate(long idTemplate) {
+        this.idTemplate = idTemplate;
+    }
+
+    public String getTagName() {
+        return tagName;
+    }
+
+    public void setTagName(String tagName) {
+        this.tagName = tagName;
+    }
+
+    public String getTagTypeName() {
+        return tagTypeName;
+    }
+
+    public void setTagTypeName(String tagTypeName) {
+        this.tagTypeName = tagTypeName;
+    }
+}

+ 196 - 3
sdWebCore/src/main/java/com/sdtool/webcore/rest/DesignRest.java

@@ -7,9 +7,7 @@ import com.sdtool.common.datas.ERPHeader;
 import com.sdtool.common.datas.HttpCode;
 import com.sdtool.common.entity.base.ProcessIdItem;
 import com.sdtool.common.entity.base.ProcessStringItem;
-import com.sdtool.common.entity.design.DesignFont;
-import com.sdtool.common.entity.design.DesignOrder;
-import com.sdtool.common.entity.design.DesignTemplate;
+import com.sdtool.common.entity.design.*;
 import com.sdtool.common.entity.site.ERPTokenUser;
 import com.sweetfish.net.http.*;
 import com.sweetfish.service.Local;
@@ -281,4 +279,199 @@ public class DesignRest extends BaseService {
         );
     }
     //endregion
+
+    //region 设计标签
+    @RestMapping(name = "queryDesignTagType", auth = true, sort = 50, comment = "获取设计标签组", methods = {"POST"})
+    @WebApiBean(result = true, type = DesignOrder.class)
+    public CompletableFuture<RMap> queryDesignTagTypeFlatten(
+            @RestParam(name = "params", comment = "搜索内容", required = false) RMap searchData,
+            @RestParam(name = "page", comment = "分页信息", required = false) PageFlipper pageFlipper,
+            @RestParam(name = "orderBy", comment = "排序", required = false) String orderBy,
+            @RestParam(name = "&", comment = "登录用户,无需传入") ERPTokenUser currentUser,
+            @RestHeader(name = ERPHeader.HTTPHEADER_DATASOURCE) String dataSourceId,
+            @RestHeader(name = ERPHeader.HTTPHEADER_SUPPLIER) String supplierCode) {
+        return CompletableFuture.supplyAsync(
+                () -> {
+                    RetResult<List<DesignTagType>> result = designService.queryDesignTagTypeFlatten(searchData, dataSourceId, Long.parseLong(supplierCode), pageFlipper);
+                    if (result.isSuccess())
+                        return RMapUtils.successV2(result.getResult(), null, result.getPageFlipper());
+                    else return RMapUtils.error(HttpCode.BAD_REQUEST.value(), result.getRetinfo());
+                }, getExecutor()
+        );
+    }
+
+    @RestMapping(name = "selectDesignTagType", auth = true, sort = 50, comment = "获取设计标签组,不分页", methods = {"POST"})
+    @WebApiBean(result = true, type = DesignOrder.class)
+    public CompletableFuture<RMap> selectDesignTagType(
+            @RestParam(name = "params", comment = "搜索内容", required = false) RMap searchData,
+            @RestParam(name = "orderBy", comment = "排序", required = false) String orderBy,
+            @RestParam(name = "&", comment = "登录用户,无需传入") ERPTokenUser currentUser,
+            @RestHeader(name = ERPHeader.HTTPHEADER_DATASOURCE) String dataSourceId,
+            @RestHeader(name = ERPHeader.HTTPHEADER_SUPPLIER) String supplierCode) {
+        return CompletableFuture.supplyAsync(
+                () -> {
+                    RetResult<List<DesignTagType>> result = designService.queryDesignTagTypeFlatten(searchData, dataSourceId, Long.parseLong(supplierCode),null);
+                    if (result.isSuccess())
+                        return RMapUtils.successV2(result.getResult(), null, result.getPageFlipper());
+                    else return RMapUtils.error(HttpCode.BAD_REQUEST.value(), result.getRetinfo());
+                }, getExecutor()
+        );
+    }
+
+    @RestMapping(name = "getDesignTagType", auth = true, sort = 50, comment = "获取设计标签组", methods = {"POST"})
+    @WebApiBean(result = true, type = DesignOrder.class)
+    public CompletableFuture<RMap> getDesignTagType(
+            @RestParam(name = "id") long id,
+            @RestParam(name = "&", comment = "登录用户,无需传入") ERPTokenUser currentUser,
+            @RestHeader(name = ERPHeader.HTTPHEADER_DATASOURCE) String dataSourceId,
+            @RestHeader(name = ERPHeader.HTTPHEADER_SUPPLIER) String supplierCode) {
+        return CompletableFuture.supplyAsync(
+                () -> {
+                    RetResult<DesignTagType> result = designService.getDesignTagType(id, dataSourceId, Long.parseLong(supplierCode), currentUser);
+                    if (result.isSuccess())
+                        return RMapUtils.successV2(result.getResult(), null, result.getPageFlipper());
+                    else return RMapUtils.error(HttpCode.BAD_REQUEST.value(), result.getRetinfo());
+                }, getExecutor()
+        );
+    }
+
+    @RestMapping(name = "newDesignTagType", auth = true, sort = 51, comment = "新增设计标签组", methods = {"POST"})
+    @WebApiBean(result = true, type = DesignTagType.class)
+    public CompletableFuture<RMap> newDesignTagType(
+            @RestBody(comment = "标签组") DesignTagType designTagType,
+            @RestParam(name = "&", comment = "登录用户,无需传入") ERPTokenUser currentUser,
+            @RestHeader(name = ERPHeader.HTTPHEADER_DATASOURCE) String dataSourceId,
+            @RestHeader(name = ERPHeader.HTTPHEADER_SUPPLIER) String supplierCode) {
+        return CompletableFuture.supplyAsync(
+                () -> {
+                    RetResult<DesignTagType> result = designService.newDesignTagType(designTagType, dataSourceId, Long.parseLong(supplierCode), currentUser);
+                    if (result.isSuccess())
+                        return RMapUtils.successV2(result.getResult(), null, null);
+                    else return RMapUtils.error(HttpCode.BAD_REQUEST.value(), result.getRetinfo());
+                }, getExecutor()
+        );
+    }
+
+    @RestMapping(name = "updateDesignTagType", auth = true, sort = 52, comment = "修改设计标签组", methods = {"POST"})
+    @WebApiBean(result = true, type = DesignTagType.class)
+    public CompletableFuture<RMap> updateDesignTagType(
+            @RestBody(comment = "标签组") DesignTagType designTagType,
+            @RestParam(name = "&", comment = "登录用户,无需传入") ERPTokenUser currentUser,
+            @RestHeader(name = ERPHeader.HTTPHEADER_DATASOURCE) String dataSourceId,
+            @RestHeader(name = ERPHeader.HTTPHEADER_SUPPLIER) String supplierCode) {
+        return CompletableFuture.supplyAsync(
+                () -> {
+                    RetResult<DesignTagType> result = designService.updateDesignTagType(designTagType, dataSourceId, Long.parseLong(supplierCode), currentUser);
+                    if (result.isSuccess())
+                        return RMapUtils.successV2(result.getResult(), null, null);
+                    else return RMapUtils.error(HttpCode.BAD_REQUEST.value(), result.getRetinfo());
+                }, getExecutor()
+        );
+    }
+
+    @RestMapping(name = "deleteDesignTagType", auth = true, sort = 53, comment = "删除设计标签组,该组的标签将自动置为未分组状态", methods = {"POST"})
+    @WebApiBean(result = true, type = DesignTagType.class)
+    public CompletableFuture<RMap> deleteDesignTagType(
+            @RestParam(name = "idDesignType", comment = "标签组id") long idDesignType,
+            @RestParam(name = "&", comment = "登录用户,无需传入") ERPTokenUser currentUser,
+            @RestHeader(name = ERPHeader.HTTPHEADER_DATASOURCE) String dataSourceId,
+            @RestHeader(name = ERPHeader.HTTPHEADER_SUPPLIER) String supplierCode) {
+        return CompletableFuture.supplyAsync(
+                () -> {
+                    RetResult<DesignTagType> result = designService.deleteDesignTagTypeFlatten(idDesignType, dataSourceId, Long.parseLong(supplierCode), currentUser);
+                    if (result.isSuccess())
+                        return RMapUtils.successV2(result.getResult(), null, null);
+                    else return RMapUtils.error(HttpCode.BAD_REQUEST.value(), result.getRetinfo());
+                }, getExecutor()
+        );
+    }
+
+    @RestMapping(name = "queryDesignTags", auth = true, sort = 60, comment = "获取设计标签", methods = {"POST"})
+    @WebApiBean(result = true, type = DesignTag.class)
+    public CompletableFuture<RMap> queryDesignTags(
+            @RestParam(name = "params", comment = "搜索内容", required = false) RMap searchData,
+            @RestParam(name = "page", comment = "分页信息", required = false) PageFlipper pageFlipper,
+            @RestParam(name = "orderBy", comment = "排序", required = false) String orderBy,
+            @RestParam(name = "&", comment = "登录用户,无需传入") ERPTokenUser currentUser,
+            @RestHeader(name = ERPHeader.HTTPHEADER_DATASOURCE) String dataSourceId,
+            @RestHeader(name = ERPHeader.HTTPHEADER_SUPPLIER) String supplierCode) {
+        return CompletableFuture.supplyAsync(
+                () -> {
+                    RetResult<List<DesignTag>> result = designService.queryDesignTags(searchData, dataSourceId, Long.parseLong(supplierCode), pageFlipper);
+                    if (result.isSuccess())
+                        return RMapUtils.successV2(result.getResult(), null, result.getPageFlipper());
+                    else return RMapUtils.error(HttpCode.BAD_REQUEST.value(), result.getRetinfo());
+                }, getExecutor()
+        );
+    }
+
+    @RestMapping(name = "newDesignTag", auth = true, sort = 61, comment = "新增设计标签", methods = {"POST"})
+    @WebApiBean(result = true, type = DesignTag.class)
+    public CompletableFuture<RMap> newDesignTag(
+            @RestBody(comment = "标签") DesignTag designTag,
+            @RestParam(name = "&", comment = "登录用户,无需传入") ERPTokenUser currentUser,
+            @RestHeader(name = ERPHeader.HTTPHEADER_DATASOURCE) String dataSourceId,
+            @RestHeader(name = ERPHeader.HTTPHEADER_SUPPLIER) String supplierCode) {
+        return CompletableFuture.supplyAsync(
+                () -> {
+                    RetResult<DesignTag> result = designService.newDesignTag(designTag, dataSourceId, Long.parseLong(supplierCode), currentUser);
+                    if (result.isSuccess())
+                        return RMapUtils.successV2(result.getResult(), null, null);
+                    else return RMapUtils.error(HttpCode.BAD_REQUEST.value(), result.getRetinfo());
+                }, getExecutor()
+        );
+    }
+
+    @RestMapping(name = "deleteDesignTag", auth = true, sort = 62, comment = "删除设计标签", methods = {"POST"})
+    @WebApiBean(result = true, type = DesignTag.class)
+    public CompletableFuture<RMap> deleteDesignTag(
+            @RestParam(name = "idDesignTag", comment = "标签id") long idDesignTag,
+            @RestParam(name = "&", comment = "登录用户,无需传入") ERPTokenUser currentUser,
+            @RestHeader(name = ERPHeader.HTTPHEADER_DATASOURCE) String dataSourceId,
+            @RestHeader(name = ERPHeader.HTTPHEADER_SUPPLIER) String supplierCode) {
+        return CompletableFuture.supplyAsync(
+                () -> {
+                    RetResult<DesignTag> result = designService.deleteDesignTag(idDesignTag, dataSourceId, Long.parseLong(supplierCode), currentUser);
+                    if (result.isSuccess())
+                        return RMapUtils.successV2(result.getResult(), null, null);
+                    else return RMapUtils.error(HttpCode.BAD_REQUEST.value(), result.getRetinfo());
+                }, getExecutor()
+        );
+    }
+
+    @RestMapping(name = "getTemplateTags", auth = true, sort = 70, comment = "获取模板已有的标签", methods = {"POST"})
+    @WebApiBean(result = true, type = TemplateTag.class)
+    public CompletableFuture<RMap> getTemplateTags(
+            @RestParam(name = "idTemplate", comment = "搜索内容") long idTemplate,
+            @RestParam(name = "&", comment = "登录用户,无需传入") ERPTokenUser currentUser,
+            @RestHeader(name = ERPHeader.HTTPHEADER_DATASOURCE) String dataSourceId,
+            @RestHeader(name = ERPHeader.HTTPHEADER_SUPPLIER) String supplierCode) {
+        return CompletableFuture.supplyAsync(
+                () -> {
+                    RetResult<List<TemplateTag>> result = designService.getTemplateTags(idTemplate, dataSourceId, Long.parseLong(supplierCode));
+                    if (result.isSuccess())
+                        return RMapUtils.successV2(result.getResult(), null, result.getPageFlipper());
+                    else return RMapUtils.error(HttpCode.BAD_REQUEST.value(), result.getRetinfo());
+                }, getExecutor()
+        );
+    }
+
+    @RestMapping(name = "modifyTemplateTags", auth = true, sort = 71, comment = "修改模板标签", methods = {"POST"})
+    @WebApiBean(result = true, type = TemplateTag.class)
+    public CompletableFuture<RMap> modifyTemplateTags(
+            @RestParam(name = "idTemplate", comment = "模板id") long idTemplate,
+            @RestBody(comment = "选定的标签") List<DesignTag> tagList,
+            @RestParam(name = "&", comment = "登录用户,无需传入") ERPTokenUser currentUser,
+            @RestHeader(name = ERPHeader.HTTPHEADER_DATASOURCE) String dataSourceId,
+            @RestHeader(name = ERPHeader.HTTPHEADER_SUPPLIER) String supplierCode) {
+        return CompletableFuture.supplyAsync(
+                () -> {
+                    RetResult<List<TemplateTag>> result = designService.modifyTemplateTags(idTemplate, tagList, dataSourceId, Long.parseLong(supplierCode), currentUser);
+                    if (result.isSuccess())
+                        return RMapUtils.successV2(result.getResult(), null, null);
+                    else return RMapUtils.error(HttpCode.BAD_REQUEST.value(), result.getRetinfo());
+                }, getExecutor()
+        );
+    }
+    //endregion
 }