Compare commits
2 Commits
884459e91a
...
632b37d5bd
| Author | SHA1 | Date | |
|---|---|---|---|
| 632b37d5bd | |||
| 75ed266532 |
@@ -43,7 +43,7 @@ dependencies {
|
|||||||
annotationProcessor 'org.projectlombok:lombok' // Lombok 注解处理
|
annotationProcessor 'org.projectlombok:lombok' // Lombok 注解处理
|
||||||
testImplementation 'org.springframework.boot:spring-boot-starter-test' // 测试框架
|
testImplementation 'org.springframework.boot:spring-boot-starter-test' // 测试框架
|
||||||
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' // thymeleaf模版引擎
|
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' // thymeleaf模版引擎
|
||||||
implementation 'com.aliyun.oss:aliyun-sdk-oss:3.17.4' // OSS SDK
|
implementation 'com.aliyun.oss:aliyun-sdk-oss:3.18.1' // OSS SDK
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.named('test') {
|
tasks.named('test') {
|
||||||
|
|||||||
@@ -71,8 +71,8 @@ public class BizFirmwareController {
|
|||||||
*/
|
*/
|
||||||
@DeleteMapping("/delete")
|
@DeleteMapping("/delete")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public Result<Firmware> delete(String id) {
|
public Result<Firmware> delete(Long id) {
|
||||||
return Result.isBool(firmwareService.removeById(id));
|
return Result.isBool(firmwareService.removeData(id));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -97,4 +97,6 @@ public class BizFirmwareController {
|
|||||||
return Result.isBool(firmwareService.uploadFile(file, id));
|
return Result.isBool(firmwareService.uploadFile(file, id));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,26 @@
|
|||||||
package com.corewing.app.modules.admin.sys;
|
package com.corewing.app.modules.admin.sys;
|
||||||
|
|
||||||
|
import com.corewing.app.common.Result;
|
||||||
|
import com.corewing.app.service.FirmwareService;
|
||||||
|
import com.corewing.app.service.SysUserService;
|
||||||
|
import com.corewing.app.service.UserService;
|
||||||
import org.springframework.stereotype.Controller;
|
import org.springframework.stereotype.Controller;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.ResponseBody;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
@Controller
|
@Controller
|
||||||
public class SysMainController {
|
public class SysMainController {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private UserService userService;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private FirmwareService firmwareService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 加载页
|
* 加载页
|
||||||
* @return
|
* @return
|
||||||
@@ -42,4 +57,17 @@ public class SysMainController {
|
|||||||
return "admin/dashboard";
|
return "admin/dashboard";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 统计
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@GetMapping("/main/statistics")
|
||||||
|
@ResponseBody
|
||||||
|
public Result<Map<String, Object>> statistics() {
|
||||||
|
Map<String, Object> result = new HashMap<>();
|
||||||
|
result.put("userCount", userService.count ());
|
||||||
|
result.put("firmwareCount", firmwareService.count());
|
||||||
|
return Result.success(result);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,4 +33,11 @@ public interface FirmwareService extends IService<Firmware> {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
boolean uploadFile(MultipartFile file, Long id);
|
boolean uploadFile(MultipartFile file, Long id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据id删除固件
|
||||||
|
* @param id
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
boolean removeData(Long id);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import com.corewing.app.mapper.FirmwareMapper;
|
|||||||
import com.corewing.app.service.FirmwareService;
|
import com.corewing.app.service.FirmwareService;
|
||||||
import com.corewing.app.util.OSSUploadUtil;
|
import com.corewing.app.util.OSSUploadUtil;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
@@ -49,5 +50,62 @@ public class FirmwareServiceImpl extends ServiceImpl<FirmwareMapper, Firmware> i
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
@Override
|
||||||
|
public boolean removeData(Long id) {
|
||||||
|
Firmware firmware = getById(id);
|
||||||
|
if(firmware != null ){
|
||||||
|
if(firmware.getDownloadUrl() != null) {
|
||||||
|
OSSUploadUtil.deleteFile(getUrlLastSegment(firmware.getDownloadUrl()));
|
||||||
|
}
|
||||||
|
return removeById(id);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取 URL 路径的最后一节(忽略查询参数 ? 和锚点 #)
|
||||||
|
* @param urlStr URL字符串
|
||||||
|
* @return 最后一节(如文件名、资源ID),异常/无路径时返回空字符串
|
||||||
|
*/
|
||||||
|
public static String getUrlLastSegment(String urlStr) {
|
||||||
|
// 1. 空值判断
|
||||||
|
if (urlStr == null || urlStr.trim().isEmpty()) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 移除查询参数(? 及后面的内容)
|
||||||
|
int queryIndex = urlStr.indexOf('?');
|
||||||
|
if (queryIndex != -1) {
|
||||||
|
urlStr = urlStr.substring(0, queryIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 移除锚点(# 及后面的内容)
|
||||||
|
int anchorIndex = urlStr.indexOf('#');
|
||||||
|
if (anchorIndex != -1) {
|
||||||
|
urlStr = urlStr.substring(0, anchorIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. 找到最后一个 "/" 的位置
|
||||||
|
int lastSlashIndex = urlStr.lastIndexOf('/');
|
||||||
|
|
||||||
|
// 5. 处理特殊情况:无 "/" 或 "/" 在末尾
|
||||||
|
if (lastSlashIndex == -1) {
|
||||||
|
// 无路径(如 "https://example.com" 或 "example.com")
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
if (lastSlashIndex == urlStr.length() - 1) {
|
||||||
|
// 路径以 "/" 结尾(如 "https://example.com/folder/"),需找倒数第二个 "/"
|
||||||
|
urlStr = urlStr.substring(0, lastSlashIndex);
|
||||||
|
lastSlashIndex = urlStr.lastIndexOf('/');
|
||||||
|
// 若倒数第二个 "/" 不存在(如 "https://example.com/"),返回空
|
||||||
|
if (lastSlashIndex == -1) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 6. 截取最后一个 "/" 后面的内容
|
||||||
|
return urlStr.substring(lastSlashIndex + 1);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,7 +47,11 @@ public class OSSUploadUtil {
|
|||||||
// 上传文件
|
// 上传文件
|
||||||
PutObjectRequest request = new PutObjectRequest(BUCKET_NAME, objectName, inputStream, metadata);
|
PutObjectRequest request = new PutObjectRequest(BUCKET_NAME, objectName, inputStream, metadata);
|
||||||
PutObjectResult result = ossClient.putObject(request);
|
PutObjectResult result = ossClient.putObject(request);
|
||||||
|
ossClient.setObjectAcl(
|
||||||
|
BUCKET_NAME, // Bucket 名称
|
||||||
|
objectName, // 刚上传的文件路径
|
||||||
|
CannedAccessControlList.PublicRead // 公共可读权限
|
||||||
|
);
|
||||||
// 生成文件访问 URL(公网访问需 Bucket 设为公共读)
|
// 生成文件访问 URL(公网访问需 Bucket 设为公共读)
|
||||||
return String.format("https://%s.%s/%s", BUCKET_NAME, ENDPOINT, objectName);
|
return String.format("https://%s.%s/%s", BUCKET_NAME, ENDPOINT, objectName);
|
||||||
} finally {
|
} finally {
|
||||||
@@ -69,6 +73,11 @@ public class OSSUploadUtil {
|
|||||||
try {
|
try {
|
||||||
File file = new File(localFilePath);
|
File file = new File(localFilePath);
|
||||||
ossClient.putObject(BUCKET_NAME, objectName, file);
|
ossClient.putObject(BUCKET_NAME, objectName, file);
|
||||||
|
ossClient.setObjectAcl(
|
||||||
|
BUCKET_NAME, // Bucket 名称
|
||||||
|
objectName, // 刚上传的文件路径
|
||||||
|
CannedAccessControlList.PublicRead // 公共可读权限
|
||||||
|
);
|
||||||
return String.format("https://%s.%s/%s", BUCKET_NAME, ENDPOINT, objectName);
|
return String.format("https://%s.%s/%s", BUCKET_NAME, ENDPOINT, objectName);
|
||||||
} finally {
|
} finally {
|
||||||
if (ossClient != null) {
|
if (ossClient != null) {
|
||||||
|
|||||||
@@ -269,7 +269,7 @@
|
|||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="mb-3 row">
|
<div class="mb-3 row" v-if="addOrEditDto.id != null">
|
||||||
<label class="col-sm-3 col-form-label">固件地址</label>
|
<label class="col-sm-3 col-form-label">固件地址</label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<input type="text" class="form-control" v-model="addOrEditDto.downloadUrl"
|
<input type="text" class="form-control" v-model="addOrEditDto.downloadUrl"
|
||||||
@@ -557,12 +557,14 @@
|
|||||||
},
|
},
|
||||||
// 打开新增模态框
|
// 打开新增模态框
|
||||||
openAddModal() {
|
openAddModal() {
|
||||||
|
this.clearForm();
|
||||||
this.addOrEditTitle = '新增';
|
this.addOrEditTitle = '新增';
|
||||||
this.modalInstances['addOrEditModel'].show();
|
this.modalInstances['addOrEditModel'].show();
|
||||||
},
|
},
|
||||||
|
|
||||||
// 打开编辑模态框
|
// 打开编辑模态框
|
||||||
openEditModal(item) {
|
openEditModal(item) {
|
||||||
|
this.clearForm();
|
||||||
this.addOrEditTitle = '编辑';
|
this.addOrEditTitle = '编辑';
|
||||||
this.addOrEditDto = item;
|
this.addOrEditDto = item;
|
||||||
this.modalInstances['addOrEditModel'].show();
|
this.modalInstances['addOrEditModel'].show();
|
||||||
|
|||||||
@@ -25,7 +25,7 @@
|
|||||||
<div class="col-md-4 mb-4">
|
<div class="col-md-4 mb-4">
|
||||||
<div class="stat-card primary">
|
<div class="stat-card primary">
|
||||||
<i class="bi bi-people-fill"></i>
|
<i class="bi bi-people-fill"></i>
|
||||||
<h3>1,234</h3>
|
<h3>{{statistics.userCount}}</h3>
|
||||||
<p>用户数</p>
|
<p>用户数</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -39,7 +39,7 @@
|
|||||||
<div class="col-md-4 mb-4">
|
<div class="col-md-4 mb-4">
|
||||||
<div class="stat-card warning">
|
<div class="stat-card warning">
|
||||||
<i class="bi bi-graph-up"></i>
|
<i class="bi bi-graph-up"></i>
|
||||||
<h3>89%</h3>
|
<h3>{{statistics.firmwareCount}}</h3>
|
||||||
<p>固件数</p>
|
<p>固件数</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -66,6 +66,10 @@
|
|||||||
username: '',
|
username: '',
|
||||||
realName: '',
|
realName: '',
|
||||||
userId: ''
|
userId: ''
|
||||||
|
},
|
||||||
|
statistics: {
|
||||||
|
userCount: 0,
|
||||||
|
firmwareCount: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -90,10 +94,23 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
async loadStatistics() {
|
||||||
|
try {
|
||||||
|
const response = await request.get('/main/statistics');
|
||||||
|
if (response.code === 200) {
|
||||||
|
this.statistics = response.data;
|
||||||
|
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取用户信息失败:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
// 加载用户信息
|
// 加载用户信息
|
||||||
this.loadUserInfo();
|
this.loadUserInfo();
|
||||||
|
// 加载统计信息
|
||||||
|
this.loadStatistics();
|
||||||
}
|
}
|
||||||
}).mount('#app');
|
}).mount('#app');
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
Reference in New Issue
Block a user