diff --git a/src/main/java/com/dreamchaser/depository_manage/controller/DepositoryController.java b/src/main/java/com/dreamchaser/depository_manage/controller/DepositoryController.java index 78545c1a..13c1922e 100644 --- a/src/main/java/com/dreamchaser/depository_manage/controller/DepositoryController.java +++ b/src/main/java/com/dreamchaser/depository_manage/controller/DepositoryController.java @@ -107,7 +107,7 @@ public class DepositoryController { // map用来存储仓库与库存的映射 Map map = new HashMap<>(); // 只获取当天 - List toDayInventoryByDNameTest = depositoryService.getToDayInventoryByDNameTest(); + List toDayInventoryByDNameTest = depositoryService.getToDayInventoryByDName(); if (weekDay == 1) { while (it.hasNext()) { int i; @@ -202,7 +202,7 @@ public class DepositoryController { instance.set(Calendar.DATE, 1); List result = new ArrayList<>(); String month = formatter.format(instance.getTime()); - List toDayInventoryByDNameTest = depositoryService.getToDayInventoryByDNameTest(); + List toDayInventoryByDNameTest = depositoryService.getToDayInventoryByDName(); for (int i = 0; i < depositoryAll.size(); i++) { String dname = depositoryAll.get(i).getDname(); Double todayDepositoryInventory = getInventoryByDname(dname, toDayInventoryByDNameTest); @@ -212,20 +212,20 @@ public class DepositoryController { } for (int num = 0; num < months.size() - 1; num++) { int k = 0; - for (int j = 0; j < depositoryAll.size(); j++) { + for (Depository depository : depositoryAll) { // 获取该仓库本月库存 Map parmIn = new HashMap<>(); Map parmOut = new HashMap<>(); // 获取每月入库总额 parmIn.put("type", 1); parmIn.put("state", "已入库"); - parmIn.put("depository_id", depositoryAll.get(j).getId()); + parmIn.put("depository_id", depository.getId()); parmIn.put("start", months.get(num + 1)); parmIn.put("end", months.get(num)); // 获取每月出库总额 parmOut.put("type", 2); parmOut.put("state", "已出库"); - parmOut.put("depository_id", depositoryAll.get(j).getId()); + parmOut.put("depository_id", depository.getId()); parmOut.put("start", months.get(num + 1)); parmOut.put("end", months.get(num)); // 获取月份中入库物料的总额 @@ -238,7 +238,7 @@ public class DepositoryController { // 测试 Double wareHouseCount1 = result.get(k++) - wareHouseInCountByMonth1 + wareHouseOutCountByMonth1; result.add(wareHouseCount1); - ((Map) sourceList.get(num)).put(depositoryAll.get(j).getDname(), wareHouseCount1); + ((Map) sourceList.get(num)).put(depository.getDname(), wareHouseCount1); } for (int i = 0; i < depositoryAll.size(); i++) { result.remove(0); @@ -275,71 +275,6 @@ public class DepositoryController { return 0.0; } - /** - * 获取之前个月的库存给地图数据 - * - * @param depositoryService - * @param depositoryRecordService - * @return - */ - public Map getBeforeInventoryOnMap(DepositoryService depositoryService, DepositoryRecordService depositoryRecordService, UserByPort userByPort) { - // 中国地图数据 - // ['product', '3月', '4月', '5月', '6月', '7月', '8月'], - // ['电子产品类', 41.1, 30.4, 65.1, 53.3, 83.8, 98.7], - Map mapData = new HashMap<>(); - List mapDataList = new ArrayList<>(); - Map previousMonth = DateUtil.getPreviousMonth(); - List months = (List) previousMonth.get("months"); - List sourceList = (List) previousMonth.get("sourceList"); - ArrayList title = new ArrayList<>(); - List depositoryAll = depositoryService.findDepositoryByAdminorgAndUser(userByPort); - title.add("product"); - for (int i = sourceList.size() - 1; i >= 0; i--) { - title.add(((Map) sourceList.get(i)).get("month")); - } - mapDataList.add(title); - List toDayInventoryByDNameTest = depositoryService.getToDayInventoryByDNameTest(); - for (Depository depository : depositoryAll) { - List productData = new ArrayList<>(); - String dname = depository.getDname(); - productData.add(dname); - Double inventoryByDname = getInventoryByDname(dname, toDayInventoryByDNameTest); - productData.add(inventoryByDname); - int k = 1; - for (int j = 0; j < months.size() - 1; j++) { - Map parmIn = new HashMap<>(); - Map parmOut = new HashMap<>(); - parmIn.put("type", 1); - parmIn.put("state", "已入库"); - parmIn.put("depository_id", depository.getId()); - parmIn.put("start", months.get(j + 1)); - parmIn.put("end", months.get(j)); - parmOut.put("type", 2); - parmOut.put("state", "已出库"); - parmOut.put("depository_id", depository.getId()); - parmOut.put("start", months.get(j + 1)); - parmOut.put("end", months.get(j)); - // 获取某个月某物料入库总额 - // 测试 - Double wareHouseInCountByMonth1 = depositoryRecordService.calMaterialTypeTopCount(parmIn); - // 获取某个月某物料出库总额 - // 测试 - Double wareHouseOutCountByMonth1 = depositoryRecordService.calMaterialTypeTopCount(parmOut); - Double wareHouseCount1 = (double) productData.get(k++) - wareHouseInCountByMonth1 + wareHouseOutCountByMonth1; - productData.add(wareHouseCount1); - } - List result = new ArrayList<>(); - result.add(productData.get(0)); - for (int j = productData.size() - 2; j > 0; j--) { - result.add(productData.get(j)); - } - mapDataList.add(result); - productData.clear(); - } - mapData.put("mapDataList", mapDataList); - return mapData; - } - /** * 根据条件查询仓库 * @@ -601,7 +536,7 @@ public class DepositoryController { List months = (List) previousMonth.get("months"); List sourceList = (List) previousMonth.get("sourceList"); for (int num = 0; num < months.size() - 1; num++) { - for (int j = 0; j < materialTypeAll.size(); j++) { + for (MaterialType materialType : materialTypeAll) { Map parm = new HashMap<>(); parm.put("type", Integer.parseInt(type)); if (Integer.parseInt(type) == 1) { @@ -611,11 +546,11 @@ public class DepositoryController { } parm.put("start", months.get(num + 1)); parm.put("end", months.get(num)); - parm.put("oldId", materialTypeAll.get(j).getOldId()); + parm.put("oldId", materialType.getOldId()); //根据条件获取月份中物料的总额 // 测试 Double materialCountByMonth1 = depositoryRecordService.calMaterialTypeTopCount(parm); - ((Map) sourceList.get(num)).put(materialTypeAll.get(j).getTname(), materialCountByMonth1); + ((Map) sourceList.get(num)).put(materialType.getTname(), materialCountByMonth1); } } @@ -843,7 +778,7 @@ public class DepositoryController { taskNum += 1; // 获取本月及之前月份各种类别入/出库总量 - Future futureForSunburstChartData = completionService.submit(new distributeTasks(depositoryAllNameAndId, type, 3, userByPort, depositoryName)); + Future futureForSunburstChartData = completionService.submit(new distributeTasks(depositoryAllNameAndId, type, 2, userByPort, depositoryName)); futureList.add(futureForSunburstChartData); taskNum += 1; @@ -1412,24 +1347,22 @@ public class DepositoryController { @Override public Object call() throws Exception { - // taskType 1为条形图3为旭日图5为库存可视化中的折线图6为库存可视化中中国地图7为库存可视化中柱状图 + // taskType 1为条形图2为旭日图3为库存可视化中的折线图4为库存可视化中的旭日图 Map result = new HashMap<>(); if (1 == taskType) { + // 获取入库 Map lineChartData = getLineChartData(depositoryAllNameAndId, type); result.put("lineChartData", lineChartData); - } else if (3 == taskType) { + } else if (2 == taskType) { List sunburstChartData = getSunburstChartData(type); result.put("sunburstChartData", sunburstChartData); - } else if (5 == taskType) { + } else if (3 == taskType) { List beforeInventoryByMonth = getBeforeInventoryByMonth(depositoryService, todayInventory, depositoryRecordService, userByPort); result.put("sourceListByMonth", beforeInventoryByMonth); - } else if (6 == taskType) { + } else if (4 == taskType) { Map thisWeekInventoryByDName = getThisWeekInventoryByDName(depositoryService, depositoryRecordService, userByPort); result.put("ThisWeekInventory", thisWeekInventoryByDName); - } else if (7 == taskType) { - Map beforeInventoryOnMap = getBeforeInventoryOnMap(depositoryService, depositoryRecordService, userByPort); - result.put("MapInventory", beforeInventoryOnMap); } return result; } diff --git a/src/main/java/com/dreamchaser/depository_manage/controller/PageController.java b/src/main/java/com/dreamchaser/depository_manage/controller/PageController.java index 2a68bc51..9adbae7e 100644 --- a/src/main/java/com/dreamchaser/depository_manage/controller/PageController.java +++ b/src/main/java/com/dreamchaser/depository_manage/controller/PageController.java @@ -1231,8 +1231,16 @@ public class PageController { } @GetMapping("/chart_stock_back") - public String chart_stock() { - return "pages/chart/chart-stock_back"; + public ModelAndView chart_stock(HttpServletRequest request) { + ModelAndView mv = new ModelAndView(); + mv.setViewName("pages/chart/chart-stock_back"); + String userAgent = request.getHeader("user-agent"); + // 判断当前使用的设备为移动端还是pc端 + boolean b = DeviceUtil.checkAgentIsMobile(userAgent); + if (b) { + mv.setViewName("pages/chart/chart-stock_mobile"); + } + return mv; } @GetMapping("/user_password") diff --git a/src/main/java/com/dreamchaser/depository_manage/mapper/DepositoryMapper.java b/src/main/java/com/dreamchaser/depository_manage/mapper/DepositoryMapper.java index 1cb6c4e1..97449d4b 100644 --- a/src/main/java/com/dreamchaser/depository_manage/mapper/DepositoryMapper.java +++ b/src/main/java/com/dreamchaser/depository_manage/mapper/DepositoryMapper.java @@ -2,6 +2,7 @@ package com.dreamchaser.depository_manage.mapper; import com.dreamchaser.depository_manage.entity.Depository; import com.dreamchaser.depository_manage.pojo.InventoryByDname; +import com.dreamchaser.depository_manage.pojo.InventoryByMTAndDepository; import org.apache.ibatis.annotations.Mapper; import org.springframework.stereotype.Repository; @@ -145,6 +146,15 @@ public interface DepositoryMapper { List getToDayInventoryByDNameTest(); + + /** + * 获取当前仓库该类型下的库存数量 + * @param map 待查询数据 + * @return + */ + InventoryByMTAndDepository getTodayInventoryByDidAndMt(Map map); + + /** * 根据条件修改状态 * @param map diff --git a/src/main/java/com/dreamchaser/depository_manage/mapper/DepositoryMapper.xml b/src/main/java/com/dreamchaser/depository_manage/mapper/DepositoryMapper.xml index a76db67a..bea434a4 100644 --- a/src/main/java/com/dreamchaser/depository_manage/mapper/DepositoryMapper.xml +++ b/src/main/java/com/dreamchaser/depository_manage/mapper/DepositoryMapper.xml @@ -22,6 +22,12 @@ + + + + + + @@ -204,7 +210,7 @@ + + + + + +
+
+ + + +
+

旭日图

+
+
+
+
+ + + + + + + + + + + + diff --git a/src/main/resources/templates/pages/scanQrCode/ScanBarCodeByNew.html b/src/main/resources/templates/pages/scanQrCode/ScanBarCodeByNew.html new file mode 100644 index 00000000..8d81f28e --- /dev/null +++ b/src/main/resources/templates/pages/scanQrCode/ScanBarCodeByNew.html @@ -0,0 +1,81 @@ + + + + + + 扫码 + + + + + + + + + + + + + + +
+ +
+ + + + \ No newline at end of file diff --git a/src/test/java/com/dreamchaser/depository_manage/InventoryByMonthTest.java b/src/test/java/com/dreamchaser/depository_manage/InventoryByMonthTest.java new file mode 100644 index 00000000..6d08b2dd --- /dev/null +++ b/src/test/java/com/dreamchaser/depository_manage/InventoryByMonthTest.java @@ -0,0 +1,283 @@ +package com.dreamchaser.depository_manage; + +import com.alibaba.fastjson.JSONObject; +import com.dreamchaser.depository_manage.entity.Depository; +import com.dreamchaser.depository_manage.entity.MaterialType; +import com.dreamchaser.depository_manage.entity.UserByPort; +import com.dreamchaser.depository_manage.pojo.InventoryByDname; +import com.dreamchaser.depository_manage.pojo.InventoryByMTAndDepository; +import com.dreamchaser.depository_manage.service.DepositoryRecordService; +import com.dreamchaser.depository_manage.service.DepositoryService; +import com.dreamchaser.depository_manage.service.MaterialService; +import com.dreamchaser.depository_manage.service.MaterialTypeService; +import com.dreamchaser.depository_manage.utils.DateUtil; +import com.dreamchaser.depository_manage.utils.LinkInterfaceUtil; +import com.dreamchaser.depository_manage.utils.ObjectFormatUtil; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +import java.text.SimpleDateFormat; +import java.util.*; +import java.util.concurrent.*; + +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +@RunWith(SpringRunner.class) +public class InventoryByMonthTest { + + + @Autowired + MaterialTypeService materialTypeService; + + @Autowired + DepositoryRecordService depositoryRecordService; + + @Autowired + MaterialService materialService; + + @Autowired + DepositoryService depositoryService; + + /** + * 获取本月之前的月份 + * + * @return + */ + public static Map getPreviousMonth() { + Calendar instance = Calendar.getInstance(); + SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM"); + Map source = new HashMap<>(); + List sourceList = new ArrayList<>(); + int month = instance.get(Calendar.MONTH) + 1; + // 获取下个月 + instance.add(Calendar.MONTH, 1); + Long nextMonth = DateUtil.DateTimeByMonthToTimeStamp(formatter.format(instance.getTime())); + ArrayList months = new ArrayList<>(); + months.add(nextMonth); + instance.add(Calendar.MONTH, -1); + + while (month > 0) { + instance.set(Calendar.MONTH, month); + instance.set(Calendar.DAY_OF_MONTH, -1); + source.put("month", month + "月"); + months.add(DateUtil.DateTimeByMonthToTimeStamp(formatter.format(instance.getTime()))); + month--; + sourceList.add(((HashMap) source).clone()); + } + instance.set(Calendar.MONTH, month); + instance.add(Calendar.MONTH, 1); + Map map = new HashMap<>(); + map.put("months", months); + map.put("sourceList", sourceList); + return map; + } + + @Test + public void main() { + + UserByPort userByPort = LinkInterfaceUtil.FindUserById(78, null); + + Map previousMonth = DateUtil.getPreviousMonth(); + // 获取所有月份 + List months = (List) previousMonth.get("months"); + // 获取月份名称 + List sourceList = (List) previousMonth.get("sourceList"); + Calendar instance = Calendar.getInstance(); + instance.add(Calendar.MONTH, 1); + instance.set(Calendar.DATE, 1); + // 获取当前用于可见的仓库列表 + List depositoryList = depositoryService.findDepositoryByAdminorgAndUser(userByPort); + // 定义每次开启的线程数 + int threadSize = depositoryList.size(); + // 开启对应数量的线程 + ExecutorService exs = Executors.newFixedThreadPool(threadSize); + // 定义线程结果集 + List> futureList = new ArrayList>(); + // 定义CompletionService + CompletionService completionService = new ExecutorCompletionService<>(exs); + // 用于存储当前仓库各物料类型的库存数 + Map> inventoryForMTAndDepository = new HashMap<>(); + // 定义结果集 + List result = new ArrayList<>(); + // 定义各 + for (int num = 0; num < months.size() - 1; num++) { + // 获取起始时间 + Object start = months.get(num + 1); + // 获取结束时间 + Object end = months.get(num); + // 获取当前计算的月份 + Object month = ((Map) sourceList.get(num)).get("month"); + for (Depository depository : depositoryList + ) { + // 获取当前仓库id + Integer depositoryId = depository.getId(); + // 判断当前当前仓库各物料类型的库存是否存在 + List inventoryByMTAndDepositories = inventoryForMTAndDepository.get(depositoryId); + if (inventoryByMTAndDepositories == null || inventoryByMTAndDepositories.size() == 0) { + // 如果不存在则获取 + inventoryByMTAndDepositories = depositoryService.getTodayInventoryInfoByDidAndMt(depositoryId); + } + // 开启线程计算结果 + Future submit = completionService.submit(new inventoryByMaterialTypeForMonth(start, end, depository, inventoryByMTAndDepositories)); + futureList.add(submit); + } + + List childItems = new ArrayList<>(); + double value = 0.0; + for (int i = 0; i < depositoryList.size(); i++) { + Object obj = null; + try { + + obj = completionService.take().get(); + Map objectMap = (Map) obj; + Integer id = ObjectFormatUtil.toInteger((objectMap).get("id")); + List inventoryByMtAndD = (List)objectMap.get("inventoryByMtAndD"); + value += ObjectFormatUtil.toDouble(objectMap.get("value")); + inventoryForMTAndDepository.put(id,inventoryByMtAndD); + (objectMap).remove("id"); + (objectMap).remove("inventoryByMtAndD"); + + childItems.add(obj); + + + } catch (InterruptedException | ExecutionException e) { + e.printStackTrace(); + } + } + Map stringObjectMap = new HashMap<>(); + stringObjectMap.put("children",childItems); + stringObjectMap.put("name",month); + stringObjectMap.put("value",value); + Random random = new Random(); + int r = random.nextInt(256); + int g = random.nextInt(256); + int b = random.nextInt(256); + Map itemStyle = new HashMap<>(); + itemStyle.put("color", "rgb(" + r + "," + g + "," + b + ")"); + stringObjectMap.put("itemStyle", itemStyle); + result.add(stringObjectMap); + + } + System.out.println(JSONObject.toJSONString(result)); + + } + + + /** + * 获取当前仓库下的库存 + * + * @param dname + * @param list + * @return + */ + public Double getInventoryByDname(String dname, List list) { + for (InventoryByDname inventoryByDname : list) { + if (dname.equals(inventoryByDname.getDname())) { + return inventoryByDname.getInventory(); + } + } + return 0.0; + } + + /** + * 用于计算当前时间段内当前仓库下各物料类型的库存 + */ + class inventoryByMaterialTypeForMonth implements Callable { + + // 开始时间 + Object start; + // 结束时间 + Object end; + // 查询仓库 + Depository depository; + // 当前仓库各物料类型库存数 + List todayInventoryInfoByDidAndMt; + + public inventoryByMaterialTypeForMonth(Object start, Object end, Depository depository, List todayInventoryInfoByDidAndMt) { + this.start = start; + this.end = end; + this.depository = depository; + this.todayInventoryInfoByDidAndMt = todayInventoryInfoByDidAndMt; + } + + @Override + public Object call() throws Exception { + // 定义当前返回结果 + Map result = new HashMap<>(); + // 定义当前仓库的总数 + double inventorySum = 0.0; + for (InventoryByMTAndDepository item : todayInventoryInfoByDidAndMt + ) { + inventorySum += (item.getInventory() / 100.0); + } + result.put("name", depository.getDname()); + result.put("id",depository.getId()); + result.put("value", inventorySum); + // 用于生产随机的颜色 + Random random = new Random(); + int r = random.nextInt(256); + int g = random.nextInt(256); + int b = random.nextInt(256); + Map itemStyle = new HashMap<>(); + itemStyle.put("color", "rgb(" + r + "," + g + "," + b + ")"); + result.put("itemStyle", itemStyle); + + // 获取所有顶级物料类型 + List materialTypeNoParent = materialTypeService.findMaterialTypeNoParent(); + Map paramIn = new HashMap<>(); + Map paramOut = new HashMap<>(); + // 获取每月入库总额 + paramIn.put("type", 1); + paramIn.put("state", "已入库"); + paramIn.put("depository_id", depository.getId()); + paramIn.put("start", start); + paramIn.put("end", end); + // 获取每月出库总额 + paramOut.put("type", 2); + paramOut.put("state", "已出库"); + paramOut.put("depository_id", depository.getId()); + paramOut.put("start", start); + paramOut.put("end", end); + List children = new ArrayList<>(); + for (MaterialType materialType : materialTypeNoParent + ) { + // 生成子数据 + Map resultItem = new HashMap<>(); + resultItem.put("name", materialType.getTname()); + // 用于生产随机的颜色 + Map itemStyleItem = new HashMap<>(); + int rt = random.nextInt(256); + int gt = random.nextInt(256); + int bt = random.nextInt(256); + itemStyleItem.put("color", "rgb(" + rt + "," + gt + "," + bt + ")"); + result.put("itemStyle", itemStyleItem); + long oldId = materialType.getOldId(); + paramIn.put("oldId", oldId); + paramOut.put("oldId", oldId); + // 获取当前类别在当前仓库下当前月份的入库总额 + Double wareHouseInCountByMonth = depositoryRecordService.calMaterialTypeTopCount(paramIn); + // 获取当前类别在当前仓库下当前月份的出库总额 + Double wareHouseOutCountByMonth = depositoryRecordService.calMaterialTypeTopCount(paramOut); + for (InventoryByMTAndDepository item : todayInventoryInfoByDidAndMt + ) { + long mtId = item.getMtId(); + // 如果是同一类型 + if (mtId == oldId) { + // 计算上个月该类型库存数 + Double wareHouseCount = item.getInventory() - wareHouseInCountByMonth + wareHouseOutCountByMonth; + // 修改库存记录 + item.setInventory(wareHouseCount); + resultItem.put("value", wareHouseCount); + } + } + children.add(resultItem); + } + result.put("children", children); + result.put("inventoryByMtAndD",todayInventoryInfoByDidAndMt); + return result; + } + } + +} diff --git a/target/classes/.restartTriggerFile b/target/classes/.restartTriggerFile new file mode 100644 index 00000000..e69de29b diff --git a/target/classes/META-INF/depository_manage (2).kotlin_module b/target/classes/META-INF/depository_manage (2).kotlin_module new file mode 100644 index 00000000..a49347af Binary files /dev/null and b/target/classes/META-INF/depository_manage (2).kotlin_module differ diff --git a/target/classes/com/dreamchaser/depository_manage/mapper/DepositoryMapper.xml b/target/classes/com/dreamchaser/depository_manage/mapper/DepositoryMapper.xml index a76db67a..bea434a4 100644 --- a/target/classes/com/dreamchaser/depository_manage/mapper/DepositoryMapper.xml +++ b/target/classes/com/dreamchaser/depository_manage/mapper/DepositoryMapper.xml @@ -22,6 +22,12 @@ + + + + + + @@ -204,7 +210,7 @@ + + + s in some browsers, due to the limited stylability of `s in IE10+.\n &::-ms-expand {\n background-color: transparent;\n border: 0;\n }\n\n // Disabled and read-only inputs\n //\n // HTML5 says that controls under a fieldset > legend:first-child won't be\n // disabled if the fieldset is disabled. Due to implementation difficulty, we\n // don't honor that edge case; we style them as disabled anyway.\n &[disabled],\n &[readonly],\n fieldset[disabled] & {\n background-color: @input-bg-disabled;\n opacity: 1; // iOS fix for unreadable disabled content; see https://github.com/twbs/bootstrap/issues/11655\n }\n\n &[disabled],\n fieldset[disabled] & {\n cursor: @cursor-disabled;\n }\n\n // Reset height for `textarea`s\n textarea& {\n height: auto;\n }\n}\n\n\n// Special styles for iOS temporal inputs\n//\n// In Mobile Safari, setting `display: block` on temporal inputs causes the\n// text within the input to become vertically misaligned. As a workaround, we\n// set a pixel line-height that matches the given height of the input, but only\n// for Safari. See https://bugs.webkit.org/show_bug.cgi?id=139848\n//\n// Note that as of 9.3, iOS doesn't support `week`.\n\n@media screen and (-webkit-min-device-pixel-ratio: 0) {\n input[type=\"date\"],\n input[type=\"time\"],\n input[type=\"datetime-local\"],\n input[type=\"month\"] {\n &.form-control {\n line-height: @input-height-base;\n }\n\n &.input-sm,\n .input-group-sm & {\n line-height: @input-height-small;\n }\n\n &.input-lg,\n .input-group-lg & {\n line-height: @input-height-large;\n }\n }\n}\n\n\n// Form groups\n//\n// Designed to help with the organization and spacing of vertical forms. For\n// horizontal forms, use the predefined grid classes.\n\n.form-group {\n margin-bottom: @form-group-margin-bottom;\n}\n\n\n// Checkboxes and radios\n//\n// Indent the labels to position radios/checkboxes as hanging controls.\n\n.radio,\n.checkbox {\n position: relative;\n display: block;\n margin-top: 10px;\n margin-bottom: 10px;\n\n // These are used on elements with