在开发之前做好设计,流程图,伪代码等前期工作是必要的。可以清晰的指导我该怎么做,而不是边做边想。看似浪费了前期的时间,实际上节省了构建代码反复思考,反复修改的时间。制定好技术方案可以交由同事进行评审,评审通过再进行开发。在与前端对接时,为了避免沟通结果与执行结果不一致的情况,应该在阐述了自己观点以后让前端再讲一遍,在达成共识的基础上进行开发,避免返工。为了表达清晰,对与功能比较复杂的逻辑,应该给出详细的流程图予以解释。以下是我开发工作前做的准备工作,伪代码不可以直接运行,毕竟是“伪代码”。
新建Amazon帖子,复制,扩展字段定制功能接口文档
API详情:
1.1API说明
新建单属性Amazon帖子(导航入口)
1.2URL
https://localhost:9002/beforeshipoms/manage/product/shelvePage/amazon/single?status=new
1.3支持格式
JSON
1.4HTTP请求方式
GET
1.5请求参数
参数 | 类型 | 说明 |
status | string | 区分新建和编辑Amazon帖子的状态值。“new”为“新建”,否则为“编辑”。 |
1.6返回结果
返回值字段 | 字段类型 | 字段说明 |
status | string | 传入的状态值 |
saleStoreList | array | 店铺集合 |
页面路径 | string | "/pages/frontend/shelves/amazonShelves/createSingleAmazonShelves" |
1.7UI效果图
==================================================================
2.1API说明
查询BaseCode接口(此接口直接复用了新产品管理页面接口,返回数据“按需索取”即可,请求参数只传入“
productCode ”。另外,旧的Amazon上架功能的“实际库存”是新建接口带过去的,因为此处已经有了库存所以 不需要了。) 。
2.2URL
https://localhost:9002/beforeshipoms/beforeship/zh/manage/product/searchBaseProduct
2.3支持格式
JSON
2.4HTTP请求方式
POST(此处不用get请求是为了复用产品管理页面的接口)
2.5请求参数
参数 | 类型 | 说明 |
productCode | string | 查询的产品code,支持模糊查询。 |
2.6返回结果
返回值字段 | 字段类型 | 字段说明 |
baseCode | String | 产品code |
name | String | 标题(名字) |
description | Stirng | 标题(描述) |
suggestSalePrice | String | 价格 |
quantity | String | 可用库存 |
countries | String | 可销售国家(新加字段) |
creationTime | Stirng | 创建信息(创建时间) |
author | String | 创建信息(创建人) |
editORnot | Boolean | 刊登情况 |
2.7返回格式
{
"status": "SUCCESS",
"data": {
"productlist": [{
"baseCode": "1141500400_4",
"editORnot": true,
"creationTime": "2018-03-22 02:41:28",
"author": "云动力oms超级管理员",
"name": "椅子",
"description": "xxxxxxxxxx",
"suggestSalePrice": 4.0,
"quantity": 299,
"countries": "US,AU"
},
......
],
"pagecount": 15,
"currentpage": 0,
"pagesize": 30,
"totalcount": 444
}
}
2.8UI效果图
==================================================================
3.1API说明
新建多属性Amazon帖子(除了加入“
个性化属性
定制”功能再没有变化,只是改变了入口。)
3.2URL
3.3UI效果图
4.1API说明
保存个性化属性接口。
4.2URL
https://localhost:9002/beforeshipoms/manage/product/shelvePage/amazon/savePersonalizedAttributes
4.3支持格式
JSON
4.4HTTP请求方式
POST
4.5请求参数
参数 | 类型 | 说明 |
string | 在request对象"data"中包含的所选分类 | |
amazonAttributeList | Map <String,String> | 在request对象"data"中传入当前用户在当前店铺所选的个性化字段,里面包括推荐值。 |
4.6返回结果
返回值字段 | 字段类型 | 字段说明 |
status | string | "SUCCESS",表示定制成功的状态值;“ERROR”表示定制失败状态。 |
data | string | 显示“个性化属性保存成功!” |
message | string | 失败信息 |
4.7UI效果图
==================================================================
5.1API说明
展示个性化属性接口。
5.2URL
https://localhost:9002/beforeshipoms/manage/product/shelvePage/amazon/showPersonalizedAttributes?categoryId=GB_a0003
5.3支持格式
JSON
5.4HTTP请求方式
GET
5.5请求参数
参数 | 类型 | 说明 |
string | 所选分类 |
5.6返回结果
参数 | 类型 | 说明 |
savedRecommendData | Map <String,List <Object>> | 当前用户在当前店铺下保存的个性化属性 |
5.7UI效果图
6.1API说明
点击复制展示同站点下的店铺列表。
6.2URL
https://localhost:9002/beforeshipoms/manage/product/shelvePage/amazon/saleStoreOfCopyShelfProduct?productCode=8796388019752
6.3支持格式
JSON
6.4HTTP请求方式
GET
6.5请求参数
参数 | 类型 | 说明 |
productCode | string | 复制帖子productCode的pk值 |
6.6返回结果
返回值字段 | 字段类型 | 字段说明 |
saleStoreList | array | 和源商品同站点下的店铺集。 |
6.7UI效果图
7.1API说明
选择分类-帖子复制接口。
7.2URL
https://localhost:9002/beforeshipoms/manage/product/shelvePage/amazon/copySingleShelfProduct?productCode=8796519058984&categoryId=GBa0003
7.3支持格式
JSON
7.4HTTP请求方式
GET
7.5请求参数
参数 | 类型 | 说明 |
productCode | string | 复制的帖子的pk值 |
string | 所选分类 | |
saleStoreId | string | 店铺 |
7.6返回结果
返回值字段 | 字段类型 | 字段说明 |
requireAndOption | object | 可选必选值得对象。 |
recommendData | Map | 推荐值。 |
urlList | array | 图片集。 |
product_type | string | 产品类型。 |
shelfProduct2IntersectionInfo | Map<String, Object>> | 返回交集信息,供前端input框展示。
|
7.7UI效果图
一,业务目标:
1,通过复制功能提高用户创建同店铺帖子的效率。
2,通过扩展“定制个性化属性”功能,避免同一用户在同一分类下需要频繁配置“相同字段”的个性化属性。
二:功能说明:
定制个性化属性功能 ,可以支持用户根据用户名和分类配置专属的“个性化”属性模板。在下次登录进来之后,选择分类,将自动去检索该用户的“个性化”属性模板并将其返回。若用户没有自己的模板将提醒用户创建自己的专属模板,以供下次使用。
三:上架功能代码执行流程:
1,定制个性化字段功能流程图:
1)保存个性化字段
2)展示个性化字段
2,复制功能执行流程图:
四:说明:
1. 选择了“扩展字段”之后,点击“确定”触发“保存个性化属性”接口。
2. 新建商品选择分类会触发“获取该分类模板信息”接口,同时触发“展示个性化属性”的接口。
3. 帖子复制功能,点击复制会触发“展示同站点下的店铺集”接口。
4. 帖子分支功能,选择完分类会触发原接口“获取该分类模板信息”接口,里面组装了源商品和目标商品信息的交集。
五:伪代码:
1. 保存个性化字段:
//Controller layer:
@Controller
@Scope("tenant")
@RequestMapping(value = "/manage")
public class ProductShelveToAmazonController extends BeforeshipAbstractPageController {
......
//保存个性化属性的 handler:
@RequireHardLogIn
@RequestMapping(value = "/product/shelvePage/amazon/savePersonalizedAttributes", method = {RequestMethod.POST})
@ResponseBody
public Object savePersonalizedAttributes(HttpServletRequest request)
{
String data = request.getParameter("data");
Object result ="";
try {
searchRestrictionService.disableSearchRestrictions();
data = URLDecoder.decode(data, "UTF-8");
result = amazonProductDataHandleService.savePersonalizedAttributes(data);
} catch (Exception e) {
e.printStackTrace();
}finally {
searchRestrictionService.enableSearchRestrictions();
}
return result;
}
......
}
=====================================================================
//service layer:
/**
*
*/
public interface BeforeshipAmazonProductDataHandleService {
......
/**
* 保存个性化属性模板
* @param data
* @return
*/
public Object savePersonalizedAttributes(final String data);
......
}
=====================================================================
//service 的具体实现:
public class BeforeshipAmazonProductDataHandleServiceImpl implementsBeforeshipAmazonProductDataHandleService {
......
@Override
public Object savePersonalizedAttributes(final String data) {
SONObject response = new JSONObject();
String saleStoreCode = null;
String uid = null;
Map<String,List<Object>> personalizedAttributes = new HashMap();
PersonalizedAttributeModel personalizedAttributeModel = null;
try{
if(data!=null){
JSONObject jsonData = JSONObject.fromObject(data);
//获取分类 categoryId
categoryId= jsonData.getString(" categoryId");
//获取当前用户登录账号 uid
UserModel user = userService.getCurrentUser();
uid = user.getUid();
//获取个性化属性 personalizedAttributes
personalizedAttributes = jsonData.getString(" personalizedAttributes ");
//创建个性化属性 model 对象
personalizedAttributeModel = modelService.create(personalizedAttributeModel .class);
personalizedAttributeModel .setCategoryId(categoryId);
personalizedAttributeModel .setUid(uid);
personalizedAttributeModel .setPersonalizedAttributes (personalizedAttributes );
//保存并刷新个性化属性模板
modelService.save(personalizedAttributeModel);
modelService.refresh(personalizedAttributeModel);
} else {
LOG.error("========== data is null: " +data);
}
}catch (Exception e) {
LOG.error("============ savePersonalizedAttributes Exception : " + e.getMessage(),e);
response.put("status", "ERROR");
response.put("message", e.getMessage());
return response;
}
response.put("status", "SUCCESS");
response.put("data", "个性化属性保存成功!");
return response;
}
......
}
2. 展示个性化字段:
//Controller layer:
@Controller
@Scope("tenant")
@RequestMapping(value = "/manage")
public class ProductShelveToAmazonController extends BeforeshipAbstractPageController {
......
//展示个性化属性的 handler:
@RequireHardLogIn
@RequestMapping(value = "/product/shelvePage/amazon/personalizedAttributes", method = {RequestMethod.GET})
@ResponseBody
public Object showPersonalizedAttributes(@RequestParam(" categoryId" ) final String categoryId)
{
//获取当前用户登录账号 uid
UserModel user = userService.getCurrentUser();
String uid = user.getUid();
Object result ="";
boolean uidIsEmpty = StringUtils.isEmpty (uid);
boolean categoryIdIsEmpty = StringUtils.isEmpty (categoryId);
if(!uidIsEmpty && ! categoryIdIsEmpty ){
result = amazonProductDataHandleService.showPersonalizedAttributes(uid, categoryId);
}
return result;
}
......
}
=====================================================================
//service layer:
public interface BeforeshipAmazonProductDataHandleService {
......
/**
* 展示个性化属性模板
* @param uid,categoryId
* @return
*/
public Object showPersonalizedAttributes(final String uid, final Sting categoryId);
......
}
=====================================================================
//service 的具体实现:
public class BeforeshipAmazonProductDataHandleServiceImpl implements BeforeshipAmazonProductDataHandleService {
......
@Override
public Object showPersonalizedAttributes(final String uid, final Sting categoryId) {
JSONObject response = new JSONObject();
SearchResult<PersonalizedAttributeModel > searchResult = null;
PersonalizedAttributeModel personalizedAttributeModel = null;
Map<String, List<Object>> personalizedAttributes= null;
try{
searchResult = beforeshipShelveProductDao.personalizedAttributes (uid, categoryId);
if (searchResult != null){
List<PersonalizedAttributeModel > personalizedAttributeList= searchResult.getResult();
if (CollectionUtils.isNotEmpty(personalizedAttributeList)){
personalizedAttributeModel = personalizedAttributeList.get(0); personalizedAttributes= personalizedAttributeModel .getPersonalizedAttributes();
if(CollectionUtils.isNotEmpty(personalizedAttributes)){
response.put("status", "SUCCESS");
response.put("data", personalizedAttributes);
return response;
}
}
}
}catch (Exception e){
LOG.error("============ showPersonalizedAttributes Exception : " + e.getMessage());
response.put("status", "ERROR");
response.put("message", "查询个性化属性模板失败!");
return response;
}
}
response.put("status", "ERROR");
response.put("message", "没有个性化属性模板,请创建!");
return response;
}
......
}
=====================================================================
//dao layer:
public interface BeforeshipShelveProductDao {
......
/**
* 展示个性化属性模板
* @param uid,categoryId
* @return
*/
SearchResult<PersonalizedAttributeModel > showPersonalizedAttributes(final String uid, final Sting categoryId);
......
}
//dao 的具体实现:
public class BeforeshipShelveProductDaoImpl implements BeforeshipShelveProductDao {
......
@Override
public SearchResult<PersonalizedAttributeModel > showPersonalizedAttributes(final String uid, final Sting categoryId)
{
searchRestrictionService.disableSearchRestrictions();
CatalogVersionModel catalogVersion = catalogVersionService.getCatalogVersion("beforeshipProductCatalog","Staged");
Map<String,Object> queryParamsMap = new HashMap<>();
StringBuilder table = new StringBuilder(ShelveProductSqlQuery.recommendDataStr);
table.append(ShelveProductSqlQuery.conditionStr);
table.append(ShelveProductSqlQuery.conditionCatalogVersion + " =?catalogVersion ");
queryParamsMap.put("catalogVersion",catalogVersion);
table.append(ShelveProductSqlQuery.conditionUid + " =?uid");
queryParamsMap.put("uid",uid);
table.append(ShelveProductSqlQuery.conditionCategoryId + " =? categoryId");
queryParamsMap.put(" categoryId",categoryId);
FlexibleSearchQuery searchQuery = new FlexibleSearchQuery(table.toString());
searchQuery.addQueryParameters(queryParamsMap);
LOG.info("showSelectRecommendData SQL : " + searchQuery.toString());
SearchResult<ShelveProductModel> searchResult = flexibleSearchService.search(searchQuery);
searchRestrictionService.enableSearchRestrictions();
return searchResult;
}
......
}
3. 点击复制返回的店铺集接口:
//Controller layer:
@Controller
@Scope("tenant")
@RequestMapping(value = "/manage")
public class ProductShelveToAmazonController extends BeforeshipAbstractPageController {
......
//点击复制返回的店铺集的 handler:
@RequireHardLogIn
@RequestMapping(value = "/product/shelvePage/amazon/showSaleStores", method = {RequestMethod.GET})
@ResponseBody
public Object saveSelectRecommendData(
@RequestParam(" productCode" ) final String productCode){
Object result ="";
ShelveProductModel shelveProductModel = null ;
try {
shelveProductModel = beforeshipPmService.obtainShelveProductByPK(productCode);
} catch (Exception e) {
e.printStackTrace();
}
SaleStoreModel saleStoreModel = shelveProductModel.getSaleStore();
String isocode = saleStoreModel.getCountry().getIsocode();
if(!StringUtils.isEmpty(isocode )){
result = amazonProductDataHandleService.getSaleStoresBySite(isocode );
}
return result;
}
......
}
=====================================================================
//service layer:
/**
*
*/
public interface BeforeshipAmazonProductDataHandleService {
......
/**
* 查询指定站点下的店铺
* @param iscode
* @return
*/
public Object getSaleStoresBySite(final String isocode );
......
}
=====================================================================
//service 的具体实现:
public class BeforeshipAmazonProductDataHandleServiceImpl implementsBeforeshipAmazonProductDataHandleService {
......
@Override
public Object getSaleStoresBySite(final String isocode ) {
JSONObject response = new JSONObject();
SearchResult<SaleStoreModel > searchResult = null;
SaleStoreModel saleStoreModel = null;
String saleStoreCode = null;
List <String> saleStoreList = null;
try{
searchResult = beforeshipShelveProductDao.getSaleStoresBySite(isocode );
if (searchResult != null){
List<SaleStoreModel > saleStoreList= searchResult.getResult();
if (CollectionUtils.isNotEmpty(saleStoreList)){
for(int i = 0; i<saleStoreList.length(); i++){
saleStoreModel = saleStoreList.get(0); saleStoreCode = saleStoreModel .getCode();
saleStoreList .add(saleStoreCode );
}
response.put("status", "SUCCESS");
response.put("data", saleStoreList );
return response;
}
}
}catch (Exception e){
LOG.error("============ showSelectRecommendData Exception : " + e.getMessage());
response.put("status", "ERROR");
response.put("message", "查询店铺失败!");
return response;
}
}
response.put("status", "ERROR");
response.put("message", "该站点下没有店铺!");
return response;
......
}
=====================================================================
//dao layer:
public interface BeforeshipShelveProductDao {
......
/**
* 查询指定站点下的店铺
* @param iscode
* @return
*/
SearchResult<PersonalizedAttributeModel > getSaleStoresBySite(final String isocode );
......
}
//dao 的具体实现:
public class BeforeshipShelveProductDaoImpl implements BeforeshipShelveProductDao {
......
@Override
public SearchResult<SaleStoreModel > getSaleStoresBySite(final String isocode )
{
searchRestrictionService.disableSearchRestrictions();
CatalogVersionModel catalogVersion = catalogVersionService.getCatalogVersion("beforeshipProductCatalog","Staged");
Map<String,Object> queryParamsMap = new HashMap<>();
StringBuilder table = new StringBuilder(ShelveProductSqlQuery.shearchSaleStoresStr);
table.append(ShelveProductSqlQuery.conditionStr);
table.append(ShelveProductSqlQuery.conditionCatalogVersion + " =?catalogVersion ");
queryParamsMap.put("catalogVersion",catalogVersion);
table.append(ShelveProductSqlQuery.conditionIsocode + " =? isocode ");
queryParamsMap.put("isocode ",isocode );
FlexibleSearchQuery searchQuery = new FlexibleSearchQuery(table.toString());
searchQuery.addQueryParameters(queryParamsMap);
LOG.info("showSelectRecommendData SQL : " + searchQuery.toString());
SearchResult<ShelveProductModel> searchResult = flexibleSearchService.search(searchQuery);
searchRestrictionService.enableSearchRestrictions();
return searchResult;
}
......
}
4. 复制商品:
//Controller layer:
//复制帖子
@RequireHardLogIn
@RequestMapping(value = "/product/copySingleShelfProduct", method = { RequestMethod.GET })
@ResponseBody
public Object copySingleShelfProduct(final String categoryId, final String saleStoreId,@RequestParam("productCode")final String productCode) {
JSONObject response = new JSONObject();
if(StringUtils.isBlank(categoryId) || StringUtils.isBlank(saleStoreId))
{
return null;
}
searchRestrictionService.disableSearchRestrictions();
final CatalogVersionModel catalogVersionModel = catalogVersionService.getCatalogVersion("beforeshipProductCatalog",
"Staged");
CategoryModel categoryModel = categoryService.getCategoryForCode(catalogVersionModel,categoryId);
searchRestrictionService.enableSearchRestrictions();
SaleStoreModel saleStoreModel = beforeshipSaleStoreService.getSalestoreByCode(saleStoreId);
if(null == saleStoreModel)
{
LOG.info(">>>>>>>>>>>.no salestore found by code : " +saleStoreId);
response.put("responseCode", 0);
response.put("response", "no salestore found by code : " +saleStoreId +" , please contact the administrator !");
String result = "";
try {
result = URLEncoder.encode(response.toString(), "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return result;
}
Map<String, Object> amzTemplateData = productDataHandleService.getAmazonTemplateData(categoryModel.getCode(),
saleStoreModel);
if(null == amzTemplateData)
{
response.put("responseCode", 0);
response.put("response", "category : " + categoryId + " without templatedata");
String result = "";
try {
result = URLEncoder.encode(response.toString(), "UTF-8");
} catch (UnsupportedEncodingException e) {
}
return result;
}
JSONObject templateJson = new JSONObject();
templateJson.put("requireAndOption", amzTemplateData.get("requireAndOption"));
templateJson.put("recommendData", amzTemplateData.get("recommendData"));
templateJson.get("recommendData");
templateJson.put("urlList", amzTemplateData.get("urlList"));
if(amzTemplateData.containsKey("product_type"))
{
templateJson.put("product_type", amzTemplateData.get("product_type"));
}
//===========================================
//获取源商品和复制的目标商品信息的交集
Map<String,Object> requireAndOption = (Map<String, Object>) amzTemplateData.get("requireAndOption");
getShelfProduct2IntersectionInfo(productCode,templateJson,requireAndOption);
//===========================================
response.put("responseCode", 1);
response.put("response", templateJson);
String result = "";
try {
result = URLEncoder.encode(response.toString(), "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return result;
}
//获取两个商品信息的交集
private Object getShelfProduct2IntersectionInfo(final String productCode,JSONObject templateJson,Map<String,Object> requireAndOption) {
ShelveProductModel shelveProductModel = null;
Map<String, Object> shelfProduct2IntersectionInfo = new HashMap<>();
Map<String, Object> tempAttributes = new HashMap<>();
try {
shelveProductModel = beforeshipPmService.obtainShelveProductByPK(productCode);
} catch (Exception e) {
e.printStackTrace();
}
//获取商品信息
Map<String, String> amazonCustomAttributes = shelveProductModel.getCustomAttributes();
getShelfProductInfo(tempAttributes,amazonCustomAttributes);
//取两个商品字段的交集
for(Map.Entry<String, Object> entry : tempAttributes.entrySet()){
if (requireAndOption.containsKey(entry.getKey())) {
shelfProduct2IntersectionInfo.put(entry.getKey(),entry.getValue());
}
}
templateJson.put("shelfProduct2IntersectionInfo",shelfProduct2IntersectionInfo);
return templateJson;
}
//获取被复制商品信息
private void getShelfProductInfo(Map<String, Object> tempAttributes,Map<String, String> customAttributes)
{
//首先,将customAttributes中正常的Key值放入tempAttributes中
Iterator<Map.Entry<String,String>> iterator = customAttributes.entrySet().iterator();
while(iterator.hasNext()){
Map.Entry<String, String> entry = iterator.next();
if ("quantity".equals(entry.getKey())) {
continue;
}
String valueStr = entry.getValue();
String valueAfterHandle = valueStr.replace("\"",""");
if (valueStr != null && valueStr.length()>0){
tempAttributes.put(entry.getKey(),valueAfterHandle);
}
}
}
=====================================================================
总结:如何提高开发效率是每个开发人员所关心的问题,拿到需求应该抑制马上进行开发的冲动。虽然在你已经胸有成竹,但我认为你仍然有必要给出说明文档,让你的思路足够清晰,而不是打了一把王者荣耀不知道自己接下来该怎么做了。而且你可以节省你和前端的沟通成本,而给出技术方案可以交由同事评审,避免因为设计,或技术问题而返工,浪费大量时间。