首页修改

This commit is contained in:
猫猫guowen
2025-10-16 16:41:09 +08:00
parent af75c2bcb1
commit fc6c0ae4dd
2 changed files with 142 additions and 114 deletions

View File

@@ -4,6 +4,11 @@ import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import com.ruoyi.device.ddj.domain.MsgDdj;
import com.ruoyi.device.ddj.service.IMsgDdjService;
import com.ruoyi.job.domain.MydoJob;
import com.ruoyi.job.service.IMydoJobService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
@@ -27,8 +32,7 @@ import com.ruoyi.device.ssj.domain.DeviceSsj;
*/ */
@RestController @RestController
@RequestMapping("/index") @RequestMapping("/index")
public class IndexController extends BaseController public class IndexController extends BaseController {
{
@Autowired @Autowired
private IDeviceCarService deviceCarService; private IDeviceCarService deviceCarService;
@@ -41,38 +45,33 @@ public class IndexController extends BaseController
@Autowired @Autowired
private IDeviceSsjService deviceSsjService; private IDeviceSsjService deviceSsjService;
@Autowired
private IMsgDdjService msgDdjService;
@Autowired
private IMydoJobService mydoJobService;
/** /**
* 获取设备统计数据 * 获取设备统计数据
*/ */
@GetMapping("/deviceStats") @GetMapping("/deviceStats")
public AjaxResult getDeviceStats() public AjaxResult getDeviceStats() {
{
try { try {
DeviceCar deviceCar = new DeviceCar(); DeviceCar deviceCar = new DeviceCar();
MsgDdj msgDdj = new MsgDdj();
DeviceSsj deviceSsj = new DeviceSsj();
List<DeviceCar> deviceList = deviceCarService.selectDeviceCarList(deviceCar); List<DeviceCar> deviceList = deviceCarService.selectDeviceCarList(deviceCar);
List<MsgDdj> msgDdjList = msgDdjService.selectMsgDdjList(msgDdj);
List<DeviceSsj> deviceSsjList = deviceSsjService.selectDeviceSsjList(deviceSsj);
Map<String, Object> stats = new HashMap<>(); Map<String, Object> count = new HashMap<>();
int agvCount = 0;
int ctuCount = 0;
int ssjCount = 0;
for (DeviceCar device : deviceList) { count.put("agvCount", deviceList.size());
String type = device.getType(); count.put("ddjCount", msgDdjList.size());
if ("1".equals(type)) { count.put("ssjCount", deviceSsjList.size());
agvCount++;
} else if ("2".equals(type)) {
ctuCount++;
} else if ("3".equals(type)) {
ssjCount++;
}
}
stats.put("agvCount", agvCount); return AjaxResult.success(count);
stats.put("ctuCount", ctuCount);
stats.put("ssjCount", ssjCount);
stats.put("totalCount", deviceList.size());
return AjaxResult.success(stats);
} catch (Exception e) { } catch (Exception e) {
return AjaxResult.error("获取设备统计数据失败"); return AjaxResult.error("获取设备统计数据失败");
} }
@@ -82,34 +81,39 @@ public class IndexController extends BaseController
* 获取任务统计数据 * 获取任务统计数据
*/ */
@GetMapping("/taskStats") @GetMapping("/taskStats")
public AjaxResult getTaskStats() public AjaxResult getTaskStats() {
{
try { try {
MydoJob mydoJob = new MydoJob();
AgvQueue agvQueue = new AgvQueue(); AgvQueue agvQueue = new AgvQueue();
List<AgvQueue> queueList = agvQueueService.selectAgvQueueList(agvQueue); List<AgvQueue> queueList = agvQueueService.selectAgvQueueList(agvQueue);
List<MydoJob> mydoJobList = mydoJobService.selectMydoJobList(mydoJob);
List<MydoJob> mydoJobFinishList = mydoJobService.selectMydoJobFinishList(mydoJob);
int pendingCount = 0; int pendingCount = 0;
int runningCount = 0; int runningCount = 0;
int finishedCount = 0;
for (AgvQueue queue : queueList) { for (MydoJob job : mydoJobList) {
String status = queue.getStatus(); String status = job.getStatus();
if ("0".equals(status)||"1".equals(status)) { if ("2".equals(status)) {
pendingCount++; pendingCount++;
} else if ("2".equals(status)||"3".equals(status)) { } else if ("3".equals(status)) {
runningCount++; runningCount++;
} }
} }
// 获取今日完成任务数 for (MydoJob Fjob : mydoJobFinishList) {
AgvQueueFinish finishQuery = new AgvQueueFinish(); String status = Fjob.getStatus();
List<AgvQueueFinish> finishList = agvQueueFinishService.selectAgvQueueFinishList(finishQuery); if ("4".equals(status)) {
int finishedCount = finishList.size(); finishedCount++;
}
}
Map<String, Object> stats = new HashMap<>(); Map<String, Object> stats = new HashMap<>();
stats.put("pendingCount", pendingCount); stats.put("pendingCount", pendingCount);
stats.put("runningCount", runningCount); stats.put("runningCount", runningCount);
stats.put("finishedCount", finishedCount); stats.put("finishedCount", finishedCount);
stats.put("totalCount", pendingCount + runningCount + finishedCount);
return AjaxResult.success(stats); return AjaxResult.success(stats);
} catch (Exception e) { } catch (Exception e) {
@@ -121,13 +125,12 @@ public class IndexController extends BaseController
* 获取当前任务队列 * 获取当前任务队列
*/ */
@GetMapping("/currentTasks") @GetMapping("/currentTasks")
public AjaxResult getCurrentTasks() public AjaxResult getCurrentTasks() {
{
try { try {
AgvQueue agvQueue = new AgvQueue(); MydoJob mydoJobParam = new MydoJob();
List<AgvQueue> taskList = agvQueueService.selectAgvQueueList(agvQueue); mydoJobParam.setStatus("3");
List<MydoJob> mydoJobList = mydoJobService.selectMydoJobList(mydoJobParam);
return AjaxResult.success(taskList); return AjaxResult.success(mydoJobList);
} catch (Exception e) { } catch (Exception e) {
return AjaxResult.error("获取当前任务队列失败"); return AjaxResult.error("获取当前任务队列失败");
} }
@@ -137,8 +140,7 @@ public class IndexController extends BaseController
* 获取运行中的设备列表 * 获取运行中的设备列表
*/ */
@GetMapping("/deviceList") @GetMapping("/deviceList")
public AjaxResult getDeviceList() public AjaxResult getDeviceList() {
{
try { try {
List<Map<String, Object>> runningDevices = new ArrayList<>(); List<Map<String, Object>> runningDevices = new ArrayList<>();
@@ -153,7 +155,7 @@ public class IndexController extends BaseController
Map<String, Object> deviceInfo = new HashMap<>(); Map<String, Object> deviceInfo = new HashMap<>();
deviceInfo.put("deviceCode", device.getDeviceCode()); deviceInfo.put("deviceCode", device.getDeviceCode());
deviceInfo.put("deviceName", device.getName()); deviceInfo.put("deviceName", device.getName());
deviceInfo.put("deviceType", "1".equals(device.getType()) ? "AGV" : "CTU"); deviceInfo.put("deviceType", "AGV");
deviceInfo.put("taskNo", device.getTaskNo()); deviceInfo.put("taskNo", device.getTaskNo());
runningDevices.add(deviceInfo); runningDevices.add(deviceInfo);
} }
@@ -176,6 +178,21 @@ public class IndexController extends BaseController
} }
} }
MsgDdj msgDdj = new MsgDdj();
List<MsgDdj> msgDdjList = msgDdjService.selectMsgDdjList(msgDdj);
for (MsgDdj ddj : msgDdjList){
Long taskNo = ddj.getRwh();
if (taskNo != 0){
HashMap<String, Object> deviceInfo = new HashMap<>();
deviceInfo.put("deviceCode",ddj.getId());
deviceInfo.put("deviceName", ddj.getName());
deviceInfo.put("deviceType", "DDJ");
deviceInfo.put("taskNo", ddj.getRwh());
runningDevices.add(deviceInfo);
}
}
return AjaxResult.success(runningDevices); return AjaxResult.success(runningDevices);
} catch (Exception e) { } catch (Exception e) {
return AjaxResult.error("获取运行中设备列表失败"); return AjaxResult.error("获取运行中设备列表失败");
@@ -186,37 +203,28 @@ public class IndexController extends BaseController
* 获取任务类型分布数据 * 获取任务类型分布数据
*/ */
@GetMapping("/taskTypeChart") @GetMapping("/taskTypeChart")
public AjaxResult getTaskTypeChart() public AjaxResult getTaskTypeChart() {
{
try { try {
AgvQueue agvQueue = new AgvQueue(); MydoJob mydoJob = new MydoJob();
List<AgvQueue> queueList = agvQueueService.selectAgvQueueList(agvQueue); List<MydoJob> mydoJobFinishList = mydoJobService.selectMydoJobFinishList(mydoJob);
AgvQueueFinish finishQuery = new AgvQueueFinish(); Map<String, Integer> inOrOutCount = new HashMap<>();
List<AgvQueueFinish> finishList = agvQueueFinishService.selectAgvQueueFinishList(finishQuery);
Map<String, Integer> taskTypeCount = new HashMap<>(); // 统计完成任务的 inOrOut 类型
for (MydoJob job : mydoJobFinishList) {
// 统计队列中的任务类型 String inOrOut = job.getInOrOut();
for (AgvQueue queue : queueList) { if (inOrOut != null && !inOrOut.isEmpty()) {
String wmsTaskType = queue.getWmsTaskType(); inOrOutCount.put(inOrOut, inOrOutCount.getOrDefault(inOrOut, 0) + 1);
if (wmsTaskType != null && !wmsTaskType.isEmpty()) {
taskTypeCount.put(wmsTaskType, taskTypeCount.getOrDefault(wmsTaskType, 0) + 1);
}
}
// 统计完成任务的类型
for (AgvQueueFinish finish : finishList) {
String wmsTaskType = finish.getWmsTaskType();
if (wmsTaskType != null && !wmsTaskType.isEmpty()) {
taskTypeCount.put(wmsTaskType, taskTypeCount.getOrDefault(wmsTaskType, 0) + 1);
} }
} }
List<Map<String, Object>> chartData = new ArrayList<>(); List<Map<String, Object>> chartData = new ArrayList<>();
for (Map.Entry<String, Integer> entry : taskTypeCount.entrySet()) { for (Map.Entry<String, Integer> entry : inOrOutCount.entrySet()) {
Map<String, Object> item = new HashMap<>(); Map<String, Object> item = new HashMap<>();
item.put("name", entry.getKey()); // 使用字典工具类获取字典标签
String dictLabel = com.ruoyi.common.utils.DictUtils.getDictLabel("in_or_out", entry.getKey());
// 如果没有找到对应的字典标签,则使用原始值
item.put("name", dictLabel != null && !dictLabel.isEmpty() ? dictLabel : entry.getKey());
item.put("value", entry.getValue()); item.put("value", entry.getValue());
chartData.add(item); chartData.add(item);
} }
@@ -231,39 +239,27 @@ public class IndexController extends BaseController
* 获取设备状态分布数据 * 获取设备状态分布数据
*/ */
@GetMapping("/deviceStatusChart") @GetMapping("/deviceStatusChart")
public AjaxResult getDeviceStatusChart() public AjaxResult getDeviceStatusChart() {
{
try { try {
Map<String, Map<String, Integer>> statusCount = new HashMap<>(); Map<String, Map<String, Integer>> statusCount = new HashMap<>();
statusCount.put("AGV", new HashMap<>()); statusCount.put("AGV", new HashMap<>());
statusCount.put("CTU", new HashMap<>()); statusCount.put("DDJ", new HashMap<>());
statusCount.put("SSJ", new HashMap<>()); statusCount.put("SSJ", new HashMap<>());
// 查询DeviceCar数据(AGV和CTU) // 查询DeviceCar数据(AGV)
DeviceCar deviceCar = new DeviceCar(); DeviceCar deviceCar = new DeviceCar();
List<DeviceCar> deviceList = deviceCarService.selectDeviceCarList(deviceCar); List<DeviceCar> deviceList = deviceCarService.selectDeviceCarList(deviceCar);
for (DeviceCar device : deviceList) { for (DeviceCar device : deviceList) {
String type = device.getType();
String taskNo = device.getTaskNo(); String taskNo = device.getTaskNo();
String deviceType = "";
String status = "其他"; String status = "其他";
if ("1".equals(type)) {
deviceType = "AGV";
} else if ("2".equals(type)) {
deviceType = "CTU";
}
// 根据taskNo判断状态:不等于空或0时为运行状态 // 根据taskNo判断状态:不等于空或0时为运行状态
if (taskNo != null && !taskNo.trim().isEmpty() && !"0".equals(taskNo.trim())) { if (taskNo != null && !taskNo.trim().isEmpty() && !"0".equals(taskNo.trim())) {
status = "运行"; status = "运行";
} }
Map<String, Integer> typeStatusCount = statusCount.get("AGV");
typeStatusCount.put(status, typeStatusCount.getOrDefault(status, 0) + 1);
if (!deviceType.isEmpty()) {
Map<String, Integer> typeStatusCount = statusCount.get(deviceType);
typeStatusCount.put(status, typeStatusCount.getOrDefault(status, 0) + 1);
}
} }
// 查询DeviceSsj数据(SSJ) // 查询DeviceSsj数据(SSJ)
@@ -283,6 +279,19 @@ public class IndexController extends BaseController
typeStatusCount.put(status, typeStatusCount.getOrDefault(status, 0) + 1); typeStatusCount.put(status, typeStatusCount.getOrDefault(status, 0) + 1);
} }
MsgDdj msgDdj = new MsgDdj();
List<MsgDdj> msgDdjList = msgDdjService.selectMsgDdjList(msgDdj);
for (MsgDdj ddj : msgDdjList){
Long taskNo = ddj.getRwh();
String status = "其他";
if (taskNo!=0){
status = "运行";
}
Map<String,Integer> typeStatusCount = statusCount.get("DDJ");
typeStatusCount.put(status,typeStatusCount.getOrDefault(status,0) + 1);
}
return AjaxResult.success(statusCount); return AjaxResult.success(statusCount);
} catch (Exception e) { } catch (Exception e) {
return AjaxResult.error("获取设备状态分布数据失败"); return AjaxResult.error("获取设备状态分布数据失败");
@@ -293,8 +302,7 @@ public class IndexController extends BaseController
* 获取首页综合数据 * 获取首页综合数据
*/ */
@GetMapping("/dashboard") @GetMapping("/dashboard")
public AjaxResult getDashboardData() public AjaxResult getDashboardData() {
{
try { try {
Map<String, Object> dashboardData = new HashMap<>(); Map<String, Object> dashboardData = new HashMap<>();

View File

@@ -2,7 +2,7 @@
<div class="app-container"> <div class="app-container">
<!-- 统计卡片 --> <!-- 统计卡片 -->
<el-row :gutter="20" class="stats-row"> <el-row :gutter="20" class="stats-row">
<el-col :span="5" > <el-col :span="4" >
<el-card class="stats-card"> <el-card class="stats-card">
<div class="stats-content"> <div class="stats-content">
<div class="stats-icon agv-icon"> <div class="stats-icon agv-icon">
@@ -10,25 +10,38 @@
</div> </div>
<div class="stats-info"> <div class="stats-info">
<div class="stats-number">{{ deviceStats.agvCount }}</div> <div class="stats-number">{{ deviceStats.agvCount }}</div>
<div class="stats-label">{{ $t('index.agvDeviceTotal') }}</div> <!-- AGV设备总数 --> <div class="stats-label">AGV设备总数</div>
</div> </div>
</div> </div>
</el-card> </el-card>
</el-col> </el-col>
<el-col :span="5"> <el-col :span="4">
<el-card class="stats-card">
<div class="stats-content">
<div class="stats-icon ddj-icon">
<i class="el-icon-cpu"></i>
</div>
<div class="stats-info">
<div class="stats-number">{{ deviceStats.ddjCount }}</div>
<div class="stats-label">堆垛机设备总数</div>
</div>
</div>
</el-card>
</el-col>
<el-col :span="4">
<el-card class="stats-card"> <el-card class="stats-card">
<div class="stats-content"> <div class="stats-content">
<div class="stats-icon ctu-icon"> <div class="stats-icon ctu-icon">
<i class="el-icon-s-grid"></i> <i class="el-icon-s-grid"></i>
</div> </div>
<div class="stats-info"> <div class="stats-info">
<div class="stats-number">{{ deviceStats.ctuCount }}</div> <div class="stats-number">{{ deviceStats.ssjCount }}</div>
<div class="stats-label">{{ $t('index.ctuDeviceTotal') }}</div> <!-- CTU设备总数 --> <div class="stats-label">输送机设备总数</div>
</div> </div>
</div> </div>
</el-card> </el-card>
</el-col> </el-col>
<el-col :span="5"> <el-col :span="4">
<el-card class="stats-card"> <el-card class="stats-card">
<div class="stats-content"> <div class="stats-content">
<div class="stats-icon queue-icon"> <div class="stats-icon queue-icon">
@@ -36,12 +49,12 @@
</div> </div>
<div class="stats-info"> <div class="stats-info">
<div class="stats-number">{{ taskStats.pendingCount }}</div> <div class="stats-number">{{ taskStats.pendingCount }}</div>
<div class="stats-label">{{ $t('index.pendingTasks') }}</div> <!-- 待执行任务 --> <div class="stats-label">待执行任务</div> <!-- 待执行任务 -->
</div> </div>
</div> </div>
</el-card> </el-card>
</el-col> </el-col>
<el-col :span="5"> <el-col :span="4">
<el-card class="stats-card"> <el-card class="stats-card">
<div class="stats-content"> <div class="stats-content">
<div class="stats-icon running-icon"> <div class="stats-icon running-icon">
@@ -49,7 +62,7 @@
</div> </div>
<div class="stats-info"> <div class="stats-info">
<div class="stats-number">{{ taskStats.runningCount }}</div> <div class="stats-number">{{ taskStats.runningCount }}</div>
<div class="stats-label">{{ $t('index.runningTasks') }}</div> <!-- 执行中任务 --> <div class="stats-label">执行中任务</div> <!-- 执行中任务 -->
</div> </div>
</div> </div>
</el-card> </el-card>
@@ -62,7 +75,7 @@
</div> </div>
<div class="stats-info"> <div class="stats-info">
<div class="stats-number">{{ taskStats.finishedCount }}</div> <div class="stats-number">{{ taskStats.finishedCount }}</div>
<div class="stats-label">{{ $t('index.completedTasks') }}</div> <!-- 已完成任务 --> <div class="stats-label">已完成任务</div> <!-- 已完成任务 -->
</div> </div>
</div> </div>
</el-card> </el-card>
@@ -74,7 +87,7 @@
<el-col :span="12"> <el-col :span="12">
<el-card class="chart-card"> <el-card class="chart-card">
<div slot="header" class="card-header"> <div slot="header" class="card-header">
<span>{{ $t('index.taskTypeDistribution') }}</span> <!-- 任务类型分布 --> <span>任务类型分布</span> <!-- 任务类型分布 -->
</div> </div>
<div id="taskTypeChart" style="height: 300px;"></div> <div id="taskTypeChart" style="height: 300px;"></div>
</el-card> </el-card>
@@ -82,7 +95,7 @@
<el-col :span="12"> <el-col :span="12">
<el-card class="chart-card"> <el-card class="chart-card">
<div slot="header" class="card-header"> <div slot="header" class="card-header">
<span>{{ $t('index.deviceStatusDistribution') }}</span> <!-- 设备状态分布 --> <span>设备状态分布</span> <!-- 设备状态分布 -->
</div> </div>
<div id="deviceStatusChart" style="height: 300px;"></div> <div id="deviceStatusChart" style="height: 300px;"></div>
</el-card> </el-card>
@@ -94,31 +107,34 @@
<el-col :span="12"> <el-col :span="12">
<el-card class="task-card"> <el-card class="task-card">
<div slot="header" class="card-header"> <div slot="header" class="card-header">
<span>{{ $t('index.currentTaskQueue') }}</span> <!-- 当前任务队列 --> <span>正执行作业列表</span> <!-- 当前任务队列 -->
<el-button type="text" @click="refreshTasks">{{ $t('index.refresh') }}</el-button> <!-- 刷新 --> <el-button type="text" @click="refreshTasks">刷新</el-button> <!-- 刷新 -->
</div> </div>
<el-table <el-table
:data="currentTasks" :data="currentTasks"
style="width: 100%" style="width: 100%"
height="300" height="300"
v-loading="loading.tasks"> v-loading="loading.tasks">
<el-table-column prop="reqCode" :label="$t('index.requestCode')" width="120"/> <!-- 请求编号 --> <el-table-column prop="inOrOut" label="作业类型" width="100">
<el-table-column prop="wmsTaskType" :label="$t('index.taskType')" width="100"> <!-- 任务类型 -->
<template slot-scope="scope"> <template slot-scope="scope">
<dict-tag :options="dict.type.wms_task_type" :value="scope.row.wmsTaskType"/> <dict-tag :options="dict.type.in_or_out" :value="scope.row.inOrOut"/>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="positionCode1" :label="$t('index.startPoint')" width="80"/> <!-- 起点 --> <el-table-column prop="jobId" label="作业ID" width="80"/>
<el-table-column prop="positionCode2" :label="$t('index.endPoint')" width="80"/> <!-- 终点 --> <el-table-column prop="taskNo" label="任务号" width="80"/>
<el-table-column prop="priority" :label="$t('index.priority')" width="80"/> <!-- 优先级 --> <el-table-column prop="executionPhase" label="执行阶段" width="80">
<el-table-column prop="status" :label="$t('index.status')" width="100"> <!-- 状态 --> <template slot-scope="scope">
<dict-tag :options="dict.type.job_ep" :value="scope.row.executionPhase"/>
</template>
</el-table-column>
<el-table-column prop="status" :label="$t('index.status')" width="100">
<template slot-scope="scope"> <template slot-scope="scope">
<el-tag :type="getStatusType(scope.row.status)"> <el-tag :type="getStatusType(scope.row.status)">
<dict-tag :options="dict.type.task_status" :value="scope.row.status"/> <dict-tag :options="dict.type.task_status" :value="scope.row.status"/>
</el-tag> </el-tag>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="reqTime" :label="$t('index.requestTime')" show-overflow-tooltip/> <!-- 请求时间 --> <el-table-column prop="createTime" label="创建时间" show-overflow-tooltip/>
</el-table> </el-table>
</el-card> </el-card>
</el-col> </el-col>
@@ -154,7 +170,7 @@ import { getDeviceStats, getTaskStats, getCurrentTasks, getDeviceList, getTaskTy
export default { export default {
name: 'Index', name: 'Index',
dicts: ['task_status', 'wms_task_type'], dicts: ['task_status', 'wms_task_type','job_ep','in_or_out'],
data() { data() {
return { return {
// 统计数据 // 统计数据
@@ -409,9 +425,9 @@ export default {
idleData[0] = statusData.AGV['其他'] || 0 // 其他 idleData[0] = statusData.AGV['其他'] || 0 // 其他
} }
// CTU数据 // CTU数据
if (statusData.CTU) { if (statusData.DDJ) {
runningData[1] = statusData.CTU['运行'] || 0 // 运行 runningData[1] = statusData.DDJ['运行'] || 0 // 运行
idleData[1] = statusData.CTU['其他'] || 0 // 其他 idleData[1] = statusData.DDJ['其他'] || 0 // 其他
} }
// SSJ数据 // SSJ数据
if (statusData.SSJ) { if (statusData.SSJ) {
@@ -436,7 +452,7 @@ export default {
}, },
xAxis: { xAxis: {
type: 'category', type: 'category',
data: ['AGV', 'CTU', 'SSJ'] data: ['AGV', 'DDJ', 'SSJ']
}, },
yAxis: { yAxis: {
type: 'value' type: 'value'
@@ -472,7 +488,7 @@ export default {
}, },
xAxis: { xAxis: {
type: 'category', type: 'category',
data: ['AGV', 'CTU', 'SSJ'] data: ['AGV', 'DDJ', 'SSJ']
}, },
yAxis: { yAxis: {
type: 'value' type: 'value'
@@ -599,6 +615,10 @@ export default {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
} }
.ddj-icon {
background: linear-gradient(135deg, #dcb536 0%, #e5845b 100%);
}
.ctu-icon { .ctu-icon {
background: linear-gradient(135deg, #36d1dc 0%, #5b86e5 100%); background: linear-gradient(135deg, #36d1dc 0%, #5b86e5 100%);
} }