diff --git a/core/core-backend/src/main/java/io/dataease/MybatisPlusGenerator.java b/core/core-backend/src/main/java/io/dataease/MybatisPlusGenerator.java index 9c3dd007e8..3007bbcb9c 100644 --- a/core/core-backend/src/main/java/io/dataease/MybatisPlusGenerator.java +++ b/core/core-backend/src/main/java/io/dataease/MybatisPlusGenerator.java @@ -14,18 +14,18 @@ public class MybatisPlusGenerator { * 第一 我嫌麻烦 * 第二 后面配置会放到nacos读起来更麻烦了 */ - private static final String url = "jdbc:mysql://127.0.0.1:3306/de_standalone?autoReconnect=false&useUnicode=true&characterEncoding=UTF-8&characterSetResults=UTF-8&zeroDateTimeBehavior=convertToNull&useSSL=false"; + private static final String url = "jdbc:mysql://localhost:3306/dataease?autoReconnect=false&useUnicode=true&characterEncoding=UTF-8&characterSetResults=UTF-8&zeroDateTimeBehavior=convertToNull&useSSL=false"; private static final String username = "root"; - private static final String password = "Password123@mysql"; + private static final String password = "123456"; /** * 业务模块例如datasource,dataset,panel等 */ - private static final String busi = "template"; + private static final String busi = "operation"; /** * 这是要生成代码的表名称 */ - private static final String TABLE_NAME = "visualization_template_extend_data"; + private static final String TABLE_NAME = "core_opt_recent"; /** * 下面两个配置基本上不用动 diff --git a/core/core-backend/src/main/java/io/dataease/commons/constants/OptConstants.java b/core/core-backend/src/main/java/io/dataease/commons/constants/OptConstants.java index 260fec2251..f0f7c95d0d 100644 --- a/core/core-backend/src/main/java/io/dataease/commons/constants/OptConstants.java +++ b/core/core-backend/src/main/java/io/dataease/commons/constants/OptConstants.java @@ -9,7 +9,7 @@ public class OptConstants { public static final class OPT_TYPE { //新建 public static final int NEW = 1; - //新建 + //更新 public static final int UPDATE = 2; //删除 public static final int DELETE = 3; @@ -26,6 +26,8 @@ public class OptConstants { public static final int DATASET = 4; //数据源 public static final int DATASOURCE = 5; + //模版 + public static final int TEMPLATE = 6; } } diff --git a/core/core-backend/src/main/java/io/dataease/operation/dao/auto/entity/CoreOptRecent.java b/core/core-backend/src/main/java/io/dataease/operation/dao/auto/entity/CoreOptRecent.java index dc9384eed7..67bdb1ed98 100644 --- a/core/core-backend/src/main/java/io/dataease/operation/dao/auto/entity/CoreOptRecent.java +++ b/core/core-backend/src/main/java/io/dataease/operation/dao/auto/entity/CoreOptRecent.java @@ -9,7 +9,7 @@ import java.io.Serializable; *

* * @author fit2cloud - * @since 2023-10-08 + * @since 2023-11-26 */ @TableName("core_opt_recent") public class CoreOptRecent implements Serializable { @@ -26,6 +26,11 @@ public class CoreOptRecent implements Serializable { */ private Long resourceId; + /** + * 资源名称 + */ + private String resourceName; + /** * 用户ID */ @@ -62,6 +67,14 @@ public class CoreOptRecent implements Serializable { this.resourceId = resourceId; } + public String getResourceName() { + return resourceName; + } + + public void setResourceName(String resourceName) { + this.resourceName = resourceName; + } + public Long getUid() { return uid; } @@ -99,6 +112,7 @@ public class CoreOptRecent implements Serializable { return "CoreOptRecent{" + "id = " + id + ", resourceId = " + resourceId + + ", resourceName = " + resourceName + ", uid = " + uid + ", resourceType = " + resourceType + ", optType = " + optType + diff --git a/core/core-backend/src/main/java/io/dataease/operation/dao/auto/mapper/CoreOptRecentMapper.java b/core/core-backend/src/main/java/io/dataease/operation/dao/auto/mapper/CoreOptRecentMapper.java index 5e7b1ebe44..fbd66686a9 100644 --- a/core/core-backend/src/main/java/io/dataease/operation/dao/auto/mapper/CoreOptRecentMapper.java +++ b/core/core-backend/src/main/java/io/dataease/operation/dao/auto/mapper/CoreOptRecentMapper.java @@ -10,7 +10,7 @@ import org.apache.ibatis.annotations.Mapper; *

* * @author fit2cloud - * @since 2023-10-08 + * @since 2023-11-26 */ @Mapper public interface CoreOptRecentMapper extends BaseMapper { diff --git a/core/core-backend/src/main/java/io/dataease/operation/manage/CoreOptRecentManage.java b/core/core-backend/src/main/java/io/dataease/operation/manage/CoreOptRecentManage.java index c736a21c2a..ff332a523e 100644 --- a/core/core-backend/src/main/java/io/dataease/operation/manage/CoreOptRecentManage.java +++ b/core/core-backend/src/main/java/io/dataease/operation/manage/CoreOptRecentManage.java @@ -1,13 +1,21 @@ package io.dataease.operation.manage; +import cn.hutool.core.collection.CollectionUtil; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import io.dataease.commons.constants.OptConstants; import io.dataease.operation.dao.auto.entity.CoreOptRecent; import io.dataease.operation.dao.auto.mapper.CoreOptRecentMapper; import io.dataease.utils.AuthUtils; import io.dataease.utils.IDUtils; +import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + @Component public class CoreOptRecentManage { @@ -15,19 +23,33 @@ public class CoreOptRecentManage { @Autowired private CoreOptRecentMapper coreStoreMapper; - public void saveOpt(Long resourceId,int resourceType,int optType) { + public void saveOpt(Long resourceId, int resourceType, int optType) { + saveOpt(resourceId, null, resourceType, optType); + } + + public void saveOpt(String resourceName, int resourceType, int optType) { + saveOpt(null, resourceName, resourceType, optType); + } + + public void saveOpt(Long resourceId, String resourceName, int resourceType, int optType) { Long uid = AuthUtils.getUser().getUserId(); QueryWrapper updateWrapper = new QueryWrapper<>(); - updateWrapper.eq("resource_id",resourceId); - updateWrapper.eq("resource_type",resourceType); - updateWrapper.eq("uid",uid); + if (resourceId != null) { + updateWrapper.eq("resource_id", resourceId); + } + if (StringUtils.isNotEmpty(resourceName)) { + updateWrapper.eq("resource_name", resourceName); + } + updateWrapper.eq("resource_type", resourceType); + updateWrapper.eq("uid", uid); CoreOptRecent updateParam = new CoreOptRecent(); updateParam.setOptType(optType); updateParam.setTime(System.currentTimeMillis()); - if(coreStoreMapper.update(updateParam,updateWrapper)==0){ + if (coreStoreMapper.update(updateParam, updateWrapper) == 0) { CoreOptRecent optRecent = new CoreOptRecent(); optRecent.setId(IDUtils.snowID()); optRecent.setResourceId(resourceId); + optRecent.setResourceName(resourceName); optRecent.setResourceType(resourceType); optRecent.setOptType(optType); optRecent.setTime(System.currentTimeMillis()); @@ -36,4 +58,17 @@ public class CoreOptRecentManage { } } + public Map findTemplateRecentUseTime() { + Long uid = AuthUtils.getUser().getUserId(); + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq("resource_type", OptConstants.OPT_RESOURCE_TYPE.TEMPLATE); + queryWrapper.eq("uid", uid); + List result = coreStoreMapper.selectList(queryWrapper); + if (CollectionUtil.isNotEmpty(result)) { + return result.stream().collect(Collectors.toMap(CoreOptRecent::getResourceName, CoreOptRecent::getTime)); + } else { + return new HashMap<>(); + } + } + } diff --git a/core/core-backend/src/main/java/io/dataease/template/manage/TemplateMarketManage.java b/core/core-backend/src/main/java/io/dataease/template/manage/TemplateMarketManage.java index 4acc7b8c34..fa8cec10b1 100644 --- a/core/core-backend/src/main/java/io/dataease/template/manage/TemplateMarketManage.java +++ b/core/core-backend/src/main/java/io/dataease/template/manage/TemplateMarketManage.java @@ -2,11 +2,13 @@ package io.dataease.template.manage; import io.dataease.api.template.dto.TemplateManageFileDTO; import io.dataease.api.template.dto.TemplateMarketDTO; +import io.dataease.api.template.dto.TemplateMarketPreviewInfoDTO; import io.dataease.api.template.response.*; import io.dataease.api.template.vo.MarketApplicationSpecVO; import io.dataease.api.template.vo.MarketMetaDataVO; import io.dataease.api.template.vo.TemplateCategoryVO; import io.dataease.exception.DEException; +import io.dataease.operation.manage.CoreOptRecentManage; import io.dataease.system.manage.SysParameterManage; import io.dataease.utils.HttpClientConfig; import io.dataease.utils.HttpClientUtil; @@ -16,10 +18,7 @@ import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Service; -import java.util.ArrayList; -import java.util.Comparator; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.stream.Collectors; /** @@ -38,6 +37,9 @@ public class TemplateMarketManage { @Resource private SysParameterManage sysParameterManage; + @Resource + private CoreOptRecentManage coreOptRecentManage; + /** * @param templateUrl template url * @Description Get template file from template market @@ -62,26 +64,91 @@ public class TemplateMarketManage { return HttpClientUtil.get(url, config); } + private MarketTemplateV2BaseResponse templateQuery(Map templateParams){ + String result = marketGet(templateParams.get("template.url") + POSTS_API_V2, null); + MarketTemplateV2BaseResponse postsResult = JsonUtil.parseObject(result, MarketTemplateV2BaseResponse.class); + return postsResult; + } + public MarketBaseResponse searchTemplate() { try { Map templateParams = sysParameterManage.groupVal("template."); - String result = marketGet(templateParams.get("template.url") + POSTS_API_V2, null); - MarketTemplateV2BaseResponse postsResult = JsonUtil.parseObject(result, MarketTemplateV2BaseResponse.class); - return baseResponseV2Trans(postsResult, templateParams.get("template.url")); + return baseResponseV2Trans(templateQuery(templateParams), templateParams.get("template.url")); } catch (Exception e) { DEException.throwException(e); } return null; } - private MarketBaseResponse baseResponseV2Trans(MarketTemplateV2BaseResponse v2BaseResponse, String url) { + public MarketBaseResponse searchTemplateRecommend() { + try { + Map templateParams = sysParameterManage.groupVal("template."); + return baseResponseV2TransRecommend(templateQuery(templateParams), templateParams.get("template.url")); + } catch (Exception e) { + DEException.throwException(e); + } + return null; + } + + public MarketPreviewBaseResponse searchTemplatePreview() { + try { + Map templateParams = sysParameterManage.groupVal("template."); + return basePreviewResponseV2Trans(templateQuery(templateParams), templateParams.get("template.url")); + } catch (Exception e) { + DEException.throwException(e); + } + return null; + } + + private MarketBaseResponse baseResponseV2TransRecommend(MarketTemplateV2BaseResponse v2BaseResponse, String url) { + Map useTime = coreOptRecentManage.findTemplateRecentUseTime(); Map categoriesMap = getCategoriesBaseV2(); List contents = new ArrayList<>(); v2BaseResponse.getItems().stream().forEach(marketTemplateV2ItemResult -> { MarketApplicationSpecVO spec = marketTemplateV2ItemResult.getApplication().getSpec(); - contents.add(new TemplateMarketDTO(spec.getReadmeName(), spec.getDisplayName(), spec.getScreenshots().get(0).getUrl(), spec.getLinks().get(0).getUrl(), categoriesMap.get(spec.getLabel()))); + if("Y".equalsIgnoreCase(spec.getSuggest())){ + contents.add(new TemplateMarketDTO(spec.getReadmeName(), spec.getDisplayName(), spec.getScreenshots().get(0).getUrl(), spec.getLinks().get(0).getUrl(), categoriesMap.get(spec.getLabel()), spec.getTemplateType(), useTime.get(spec.getReadmeName()),"Y")); + } }); - return new MarketBaseResponse(url, contents); + // 最近使用排序 + Collections.sort(contents); + return new MarketBaseResponse(url,contents); + } + + private MarketBaseResponse baseResponseV2Trans(MarketTemplateV2BaseResponse v2BaseResponse, String url) { + Map useTime = coreOptRecentManage.findTemplateRecentUseTime(); + Map categoriesMap = getCategoriesBaseV2(); + List contents = new ArrayList<>(); + v2BaseResponse.getItems().stream().forEach(marketTemplateV2ItemResult -> { + MarketApplicationSpecVO spec = marketTemplateV2ItemResult.getApplication().getSpec(); + contents.add(new TemplateMarketDTO(spec.getReadmeName(), spec.getDisplayName(), spec.getScreenshots().get(0).getUrl(), spec.getLinks().get(0).getUrl(), categoriesMap.get(spec.getLabel()), spec.getTemplateType(), useTime.get(spec.getReadmeName()),spec.getSuggest())); + }); + // 最近使用排序 + Collections.sort(contents); + return new MarketBaseResponse(url,contents); + } + + private MarketPreviewBaseResponse basePreviewResponseV2Trans(MarketTemplateV2BaseResponse v2BaseResponse, String url) { + Map useTime = coreOptRecentManage.findTemplateRecentUseTime(); + Map categoriesMap = getCategoriesBaseV2(); + List categories = new ArrayList<>(); + List result = new ArrayList<>(); + categoriesMap.forEach((key,value)->{ + if(!"全部".equalsIgnoreCase(value)){ + categories.add(value); + List contents = new ArrayList<>(); + v2BaseResponse.getItems().stream().forEach(marketTemplateV2ItemResult -> { + MarketApplicationSpecVO spec = marketTemplateV2ItemResult.getApplication().getSpec(); + if(key.equalsIgnoreCase(spec.getLabel())){ + contents.add(new TemplateMarketDTO(spec.getReadmeName(), spec.getDisplayName(), spec.getScreenshots().get(0).getUrl(), spec.getLinks().get(0).getUrl(), categoriesMap.get(spec.getLabel()), spec.getTemplateType(), useTime.get(spec.getReadmeName()),spec.getSuggest())); + } + }); + Collections.sort(contents); + result.add(new TemplateMarketPreviewInfoDTO(value,contents)); + } + }); + // 最近使用排序 + return new MarketPreviewBaseResponse(url,categories,result); } public MarketBaseResponse searchTemplateV1() { @@ -115,6 +182,13 @@ public class TemplateMarketManage { .collect(Collectors.toList()); } + public List getCategoriesObject() { + List result = getCategoriesV2(); + result.add(0, new MarketMetaDataVO("suggest", "推荐")); + result.add(0, new MarketMetaDataVO("recent", "最近使用")); + return result; + } + public Map getCategoriesBaseV2() { Map categories = getCategoriesV2().stream() .collect(Collectors.toMap(MarketMetaDataVO::getSlug, MarketMetaDataVO::getLabel)); diff --git a/core/core-backend/src/main/java/io/dataease/template/service/TemplateMarketService.java b/core/core-backend/src/main/java/io/dataease/template/service/TemplateMarketService.java index f390346e04..d3b6ad3f5e 100644 --- a/core/core-backend/src/main/java/io/dataease/template/service/TemplateMarketService.java +++ b/core/core-backend/src/main/java/io/dataease/template/service/TemplateMarketService.java @@ -2,6 +2,8 @@ package io.dataease.template.service; import io.dataease.api.template.TemplateMarketApi; import io.dataease.api.template.response.MarketBaseResponse; +import io.dataease.api.template.response.MarketPreviewBaseResponse; +import io.dataease.api.template.vo.MarketMetaDataVO; import io.dataease.template.manage.TemplateMarketManage; import jakarta.annotation.Resource; import org.springframework.web.bind.annotation.RequestMapping; @@ -23,9 +25,23 @@ public class TemplateMarketService implements TemplateMarketApi { public MarketBaseResponse searchTemplate() { return templateMarketManage.searchTemplate(); } + @Override + public MarketBaseResponse searchTemplateRecommend() { + return templateMarketManage.searchTemplateRecommend(); + } + + @Override + public MarketPreviewBaseResponse searchTemplatePreview() { + return templateMarketManage.searchTemplatePreview(); + } @Override public List categories() { return templateMarketManage.getCategories(); } + + @Override + public List categoriesObject() { + return templateMarketManage.getCategoriesObject(); + } } diff --git a/core/core-backend/src/main/java/io/dataease/visualization/server/DataVisualizationServer.java b/core/core-backend/src/main/java/io/dataease/visualization/server/DataVisualizationServer.java index a4474aeb86..1f848e0bc5 100644 --- a/core/core-backend/src/main/java/io/dataease/visualization/server/DataVisualizationServer.java +++ b/core/core-backend/src/main/java/io/dataease/visualization/server/DataVisualizationServer.java @@ -15,11 +15,13 @@ import io.dataease.chart.dao.auto.mapper.CoreChartViewMapper; import io.dataease.chart.manage.ChartDataManage; import io.dataease.chart.manage.ChartViewManege; import io.dataease.commons.constants.DataVisualizationConstants; +import io.dataease.commons.constants.OptConstants; import io.dataease.constant.CommonConstants; import io.dataease.exception.DEException; import io.dataease.license.config.XpackInteract; import io.dataease.model.BusiNodeRequest; import io.dataease.model.BusiNodeVO; +import io.dataease.operation.manage.CoreOptRecentManage; import io.dataease.template.dao.auto.entity.VisualizationTemplate; import io.dataease.template.dao.auto.entity.VisualizationTemplateExtendData; import io.dataease.template.dao.auto.mapper.VisualizationTemplateExtendDataMapper; @@ -79,6 +81,8 @@ public class DataVisualizationServer implements DataVisualizationApi { @Resource private VisualizationTemplateExtendDataMapper templateExtendDataMapper; + @Resource + private CoreOptRecentManage coreOptRecentManage; @Override @XpackInteract(value = "dataVisualizationServer", original = true) @@ -257,6 +261,8 @@ public class DataVisualizationServer implements DataVisualizationApi { staticResource = templateFileInfo.getStaticResource(); name = templateFileInfo.getName(); dvType = templateFileInfo.getDvType(); + // 模版市场记录 + coreOptRecentManage.saveOpt(request.getResourceName(), OptConstants.OPT_RESOURCE_TYPE.TEMPLATE,OptConstants.OPT_TYPE.NEW); } // 解析动态数据 Map dynamicDataMap = JsonUtil.parseObject(dynamicData, Map.class); diff --git a/core/core-backend/src/main/resources/db/desktop/V2.1__ddl.sql b/core/core-backend/src/main/resources/db/desktop/V2.1__ddl.sql index 74118a1f43..22285c1330 100644 --- a/core/core-backend/src/main/resources/db/desktop/V2.1__ddl.sql +++ b/core/core-backend/src/main/resources/db/desktop/V2.1__ddl.sql @@ -18,7 +18,7 @@ CREATE TABLE `visualization_template` ( BEGIN; INSERT INTO `core_menu` -VALUES (19, 0, 2, 'template-market', 'template-market', 4, NULL, '/template-market', 0, 1, 0); +VALUES (19, 0, 2, 'template-market', 'template-market', 4, NULL, '/template-market', 0, 1, 1); INSERT INTO `core_menu` VALUES (20, 15, 2, 'template-setting', 'system/template-setting', 4, 'icon_template', '/template-setting', 0, 1, 1); COMMIT; @@ -33,3 +33,7 @@ CREATE TABLE `visualization_template_extend_data` ( `copy_id` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`) ); + +ALTER TABLE `core_opt_recent` + MODIFY COLUMN `resource_id` bigint NULL COMMENT '资源ID' AFTER `id`, + ADD COLUMN `resource_name` varchar(255) NULL COMMENT '资源名称' AFTER `resource_id`; \ No newline at end of file diff --git a/core/core-backend/src/main/resources/db/migration/V2.1__ddl.sql b/core/core-backend/src/main/resources/db/migration/V2.1__ddl.sql index bc45bca231..6d795fc843 100644 --- a/core/core-backend/src/main/resources/db/migration/V2.1__ddl.sql +++ b/core/core-backend/src/main/resources/db/migration/V2.1__ddl.sql @@ -20,7 +20,7 @@ CREATE TABLE `visualization_template` BEGIN; INSERT INTO `core_menu` -VALUES (19, 0, 2, 'template-market', 'template-market', 4, NULL, '/template-market', 0, 1, 0); +VALUES (19, 0, 2, 'template-market', 'template-market', 4, NULL, '/template-market', 0, 1, 1); INSERT INTO `core_menu` VALUES (20, 15, 2, 'template-setting', 'system/template-setting', 4, 'icon_template', '/template-setting', 0, 1, 1); COMMIT; @@ -35,3 +35,8 @@ CREATE TABLE `visualization_template_extend_data` ( `copy_id` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`) ); + + +ALTER TABLE `core_opt_recent` + MODIFY COLUMN `resource_id` bigint NULL COMMENT '资源ID' AFTER `id`, + ADD COLUMN `resource_name` varchar(255) NULL COMMENT '资源名称' AFTER `resource_id`; \ No newline at end of file diff --git a/core/core-frontend/src/api/templateMarket.ts b/core/core-frontend/src/api/templateMarket.ts index d68173a385..30d25d15af 100644 --- a/core/core-frontend/src/api/templateMarket.ts +++ b/core/core-frontend/src/api/templateMarket.ts @@ -6,8 +6,26 @@ export function searchMarket() { }) } +export function searchMarketRecommend() { + return request.get({ + url: '/templateMarket/searchRecommend' + }) +} + +export function searchMarketPreview() { + return request.get({ + url: '/templateMarket/searchPreview' + }) +} + export function getCategories() { return request.get({ url: '/templateMarket/categories' }) } + +export function getCategoriesObject() { + return request.get({ + url: '/templateMarket/categoriesObject' + }) +} diff --git a/core/core-frontend/src/assets/svg/market-expand.svg b/core/core-frontend/src/assets/svg/market-expand.svg new file mode 100644 index 0000000000..278a7efb75 --- /dev/null +++ b/core/core-frontend/src/assets/svg/market-expand.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/core-frontend/src/assets/svg/market-retract.svg b/core/core-frontend/src/assets/svg/market-retract.svg new file mode 100644 index 0000000000..64fd48694a --- /dev/null +++ b/core/core-frontend/src/assets/svg/market-retract.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/core/core-frontend/src/assets/svg/no_result.svg b/core/core-frontend/src/assets/svg/no_result.svg index 78a9df2c8f..2621d6b540 100644 --- a/core/core-frontend/src/assets/svg/no_result.svg +++ b/core/core-frontend/src/assets/svg/no_result.svg @@ -1,5 +1,14 @@ - - - - + + + + + + + + + + + + + diff --git a/core/core-frontend/src/layout/components/HeaderTemplateMarket.vue b/core/core-frontend/src/layout/components/HeaderTemplateMarket.vue new file mode 100644 index 0000000000..7a39934bde --- /dev/null +++ b/core/core-frontend/src/layout/components/HeaderTemplateMarket.vue @@ -0,0 +1,94 @@ + + +模版市场 +
+ + + + + 返回工作台 + + + +
+ + + + + + diff --git a/core/core-frontend/src/layout/index.vue b/core/core-frontend/src/layout/index.vue index a3d5f1448e..53fa889f56 100644 --- a/core/core-frontend/src/layout/index.vue +++ b/core/core-frontend/src/layout/index.vue @@ -7,14 +7,17 @@ import Menu from './components/Menu.vue' import Main from './components/Main.vue' import { ElContainer } from 'element-plus-secondary' import { useRoute } from 'vue-router' +import HeaderTemplateMarket from '@/layout/components/HeaderTemplateMarket.vue' const route = useRoute() const systemMenu = computed(() => route.path.includes('system')) const settingMenu = computed(() => route.path.includes('sys-setting')) +const templateMarketMenu = computed(() => route.path.includes('template-market'))