项目需求、任务以及模块精简
This commit is contained in:
@@ -43,7 +43,7 @@ import java.io.Serial;
|
|||||||
@Column(name = "contract_status", attrName = "contractStatus", label = "合同状态"),
|
@Column(name = "contract_status", attrName = "contractStatus", label = "合同状态"),
|
||||||
@Column(name = "payment_status", attrName = "paymentStatus", label = "付款状态"),
|
@Column(name = "payment_status", attrName = "paymentStatus", label = "付款状态"),
|
||||||
@Column(name = "remark", attrName = "remark", label = "合同备注", isQuery = false),
|
@Column(name = "remark", attrName = "remark", label = "合同备注", isQuery = false),
|
||||||
@Column(name = "create_user", attrName = "createUser", label = "创建人员", isUpdate = false, isQuery = false),
|
@Column(name = "create_user", attrName = "createUser", label = "创建人员", isUpdate = false),
|
||||||
@Column(name = "update_time", attrName = "updateTime", label = "更新时间", isQuery = false, isUpdateForce = true),
|
@Column(name = "update_time", attrName = "updateTime", label = "更新时间", isQuery = false, isUpdateForce = true),
|
||||||
}, joinTable = {
|
}, joinTable = {
|
||||||
@JoinTable(type = Type.LEFT_JOIN, entity = MyProjectInfo.class, alias = "b",
|
@JoinTable(type = Type.LEFT_JOIN, entity = MyProjectInfo.class, alias = "b",
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ import java.io.Serial;
|
|||||||
@Column(name = "actual_end_time", attrName = "actualEndTime", label = "实际结束", isQuery = false, isUpdateForce = true),
|
@Column(name = "actual_end_time", attrName = "actualEndTime", label = "实际结束", isQuery = false, isUpdateForce = true),
|
||||||
@Column(name = "work_hours", attrName = "workHours", label = "工时", isQuery = false),
|
@Column(name = "work_hours", attrName = "workHours", label = "工时", isQuery = false),
|
||||||
@Column(name = "remark", attrName = "remark", label = "备注", queryType = QueryType.LIKE),
|
@Column(name = "remark", attrName = "remark", label = "备注", queryType = QueryType.LIKE),
|
||||||
@Column(name = "create_user", attrName = "createUser", label = "创建人员", isUpdate = false, isQuery = false),
|
@Column(name = "create_user", attrName = "createUser", label = "创建人员", isUpdate = false),
|
||||||
@Column(name = "update_time", attrName = "updateTime", label = "更新时间", isUpdate = false, isQuery = false, isUpdateForce = true),
|
@Column(name = "update_time", attrName = "updateTime", label = "更新时间", isUpdate = false, isQuery = false, isUpdateForce = true),
|
||||||
}, joinTable = {
|
}, joinTable = {
|
||||||
@JoinTable(type = Type.LEFT_JOIN, entity = MyProjectInfo.class, alias = "b",
|
@JoinTable(type = Type.LEFT_JOIN, entity = MyProjectInfo.class, alias = "b",
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.jeesite.modules.biz.web;
|
package com.jeesite.modules.biz.web;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
@@ -26,6 +27,7 @@ import com.jeesite.modules.biz.service.MyProjectContractService;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 项目合同 Controller
|
* 项目合同 Controller
|
||||||
|
*
|
||||||
* @author gaoxq
|
* @author gaoxq
|
||||||
* @version 2026-04-04
|
* @version 2026-04-04
|
||||||
*/
|
*/
|
||||||
@@ -33,114 +35,119 @@ import com.jeesite.modules.biz.service.MyProjectContractService;
|
|||||||
@RequestMapping(value = "${adminPath}/biz/myProjectContract")
|
@RequestMapping(value = "${adminPath}/biz/myProjectContract")
|
||||||
public class MyProjectContractController extends BaseController {
|
public class MyProjectContractController extends BaseController {
|
||||||
|
|
||||||
private final MyProjectContractService myProjectContractService;
|
private final MyProjectContractService myProjectContractService;
|
||||||
|
|
||||||
public MyProjectContractController(MyProjectContractService myProjectContractService) {
|
public MyProjectContractController(MyProjectContractService myProjectContractService) {
|
||||||
this.myProjectContractService = myProjectContractService;
|
this.myProjectContractService = myProjectContractService;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取数据
|
* 获取数据
|
||||||
*/
|
*/
|
||||||
@ModelAttribute
|
@ModelAttribute
|
||||||
public MyProjectContract get(String contractId, boolean isNewRecord) {
|
public MyProjectContract get(String contractId, boolean isNewRecord) {
|
||||||
return myProjectContractService.get(contractId, isNewRecord);
|
return myProjectContractService.get(contractId, isNewRecord);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询列表
|
* 查询列表
|
||||||
*/
|
*/
|
||||||
@RequiresPermissions("biz:myProjectContract:view")
|
@RequiresPermissions("biz:myProjectContract:view")
|
||||||
@RequestMapping(value = {"list", ""})
|
@RequestMapping(value = {"list", ""})
|
||||||
public String list(MyProjectContract myProjectContract, Model model) {
|
public String list(MyProjectContract myProjectContract, Model model) {
|
||||||
model.addAttribute("myProjectContract", myProjectContract);
|
model.addAttribute("myProjectContract", myProjectContract);
|
||||||
return "modules/biz/myProjectContractList";
|
return "modules/biz/myProjectContractList";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询列表数据
|
* 查询列表数据
|
||||||
*/
|
*/
|
||||||
@RequiresPermissions("biz:myProjectContract:view")
|
@RequiresPermissions("biz:myProjectContract:view")
|
||||||
@RequestMapping(value = "listData")
|
@RequestMapping(value = "listData")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public Page<MyProjectContract> listData(MyProjectContract myProjectContract, HttpServletRequest request, HttpServletResponse response) {
|
public Page<MyProjectContract> listData(MyProjectContract myProjectContract, HttpServletRequest request, HttpServletResponse response) {
|
||||||
myProjectContract.setPage(new Page<>(request, response));
|
myProjectContract.setPage(new Page<>(request, response));
|
||||||
Page<MyProjectContract> page = myProjectContractService.findPage(myProjectContract);
|
Page<MyProjectContract> page = myProjectContractService.findPage(myProjectContract);
|
||||||
return page;
|
return page;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查看编辑表单
|
* 查看编辑表单
|
||||||
*/
|
*/
|
||||||
@RequiresPermissions("biz:myProjectContract:view")
|
@RequiresPermissions("biz:myProjectContract:view")
|
||||||
@RequestMapping(value = "form")
|
@RequestMapping(value = "form")
|
||||||
public String form(MyProjectContract myProjectContract, Model model) {
|
public String form(MyProjectContract myProjectContract, Model model) {
|
||||||
model.addAttribute("myProjectContract", myProjectContract);
|
model.addAttribute("myProjectContract", myProjectContract);
|
||||||
return "modules/biz/myProjectContractForm";
|
return "modules/biz/myProjectContractForm";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 保存数据
|
* 保存数据
|
||||||
*/
|
*/
|
||||||
@RequiresPermissions("biz:myProjectContract:edit")
|
@RequiresPermissions("biz:myProjectContract:edit")
|
||||||
@PostMapping(value = "save")
|
@PostMapping(value = "save")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public String save(@Validated MyProjectContract myProjectContract) {
|
public String save(@Validated MyProjectContract myProjectContract) {
|
||||||
myProjectContractService.save(myProjectContract);
|
myProjectContractService.save(myProjectContract);
|
||||||
return renderResult(Global.TRUE, text("保存合同成功!"));
|
return renderResult(Global.TRUE, text("保存合同成功!"));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 导出数据
|
* 导出数据
|
||||||
*/
|
*/
|
||||||
@RequiresPermissions("biz:myProjectContract:view")
|
@RequiresPermissions("biz:myProjectContract:view")
|
||||||
@RequestMapping(value = "exportData")
|
@RequestMapping(value = "exportData")
|
||||||
public void exportData(MyProjectContract myProjectContract, HttpServletResponse response) {
|
public void exportData(MyProjectContract myProjectContract, HttpServletResponse response) {
|
||||||
List<MyProjectContract> list = myProjectContractService.findList(myProjectContract);
|
List<MyProjectContract> list = myProjectContractService.findList(myProjectContract);
|
||||||
String fileName = "合同" + DateUtils.getDate("yyyyMMddHHmmss") + ".xlsx";
|
String fileName = "合同" + DateUtils.getDate("yyyyMMddHHmmss") + ".xlsx";
|
||||||
try(ExcelExport ee = new ExcelExport("合同", MyProjectContract.class)){
|
try (ExcelExport ee = new ExcelExport("合同", MyProjectContract.class)) {
|
||||||
ee.setDataList(list).write(response, fileName);
|
ee.setDataList(list).write(response, fileName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 下载模板
|
* 下载模板
|
||||||
*/
|
*/
|
||||||
@RequiresPermissions("biz:myProjectContract:view")
|
@RequiresPermissions("biz:myProjectContract:view")
|
||||||
@RequestMapping(value = "importTemplate")
|
@RequestMapping(value = "importTemplate")
|
||||||
public void importTemplate(HttpServletResponse response) {
|
public void importTemplate(HttpServletResponse response) {
|
||||||
MyProjectContract myProjectContract = new MyProjectContract();
|
MyProjectContract myProjectContract = new MyProjectContract();
|
||||||
List<MyProjectContract> list = ListUtils.newArrayList(myProjectContract);
|
List<MyProjectContract> list = ListUtils.newArrayList(myProjectContract);
|
||||||
String fileName = "合同模板.xlsx";
|
String fileName = "合同模板.xlsx";
|
||||||
try(ExcelExport ee = new ExcelExport("合同", MyProjectContract.class, Type.IMPORT)){
|
try (ExcelExport ee = new ExcelExport("合同", MyProjectContract.class, Type.IMPORT)) {
|
||||||
ee.setDataList(list).write(response, fileName);
|
ee.setDataList(list).write(response, fileName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 导入数据
|
* 导入数据
|
||||||
*/
|
*/
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
@RequiresPermissions("biz:myProjectContract:edit")
|
@RequiresPermissions("biz:myProjectContract:edit")
|
||||||
@PostMapping(value = "importData")
|
@PostMapping(value = "importData")
|
||||||
public String importData(MultipartFile file) {
|
public String importData(MultipartFile file) {
|
||||||
try {
|
try {
|
||||||
String message = myProjectContractService.importData(file);
|
String message = myProjectContractService.importData(file);
|
||||||
return renderResult(Global.TRUE, "posfull:"+message);
|
return renderResult(Global.TRUE, "posfull:" + message);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
return renderResult(Global.FALSE, "posfull:"+ex.getMessage());
|
return renderResult(Global.FALSE, "posfull:" + ex.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 删除数据
|
* 删除数据
|
||||||
*/
|
*/
|
||||||
@RequiresPermissions("biz:myProjectContract:edit")
|
@RequiresPermissions("biz:myProjectContract:edit")
|
||||||
@RequestMapping(value = "delete")
|
@RequestMapping(value = "delete")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public String delete(MyProjectContract myProjectContract) {
|
public String delete(MyProjectContract myProjectContract) {
|
||||||
myProjectContractService.delete(myProjectContract);
|
myProjectContractService.delete(myProjectContract);
|
||||||
return renderResult(Global.TRUE, text("删除合同成功!"));
|
return renderResult(Global.TRUE, text("删除合同成功!"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@RequestMapping(value = "listAll")
|
||||||
|
@ResponseBody
|
||||||
|
public List<MyProjectContract> listAll(MyProjectContract myProjectContract) {
|
||||||
|
return myProjectContractService.findList(myProjectContract);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.jeesite.modules.biz.web;
|
package com.jeesite.modules.biz.web;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
@@ -26,6 +27,7 @@ import com.jeesite.modules.biz.service.MyProjectTaskService;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 项目任务 Controller
|
* 项目任务 Controller
|
||||||
|
*
|
||||||
* @author gaoxq
|
* @author gaoxq
|
||||||
* @version 2026-04-04
|
* @version 2026-04-04
|
||||||
*/
|
*/
|
||||||
@@ -33,114 +35,121 @@ import com.jeesite.modules.biz.service.MyProjectTaskService;
|
|||||||
@RequestMapping(value = "${adminPath}/biz/myProjectTask")
|
@RequestMapping(value = "${adminPath}/biz/myProjectTask")
|
||||||
public class MyProjectTaskController extends BaseController {
|
public class MyProjectTaskController extends BaseController {
|
||||||
|
|
||||||
private final MyProjectTaskService myProjectTaskService;
|
private final MyProjectTaskService myProjectTaskService;
|
||||||
|
|
||||||
public MyProjectTaskController(MyProjectTaskService myProjectTaskService) {
|
public MyProjectTaskController(MyProjectTaskService myProjectTaskService) {
|
||||||
this.myProjectTaskService = myProjectTaskService;
|
this.myProjectTaskService = myProjectTaskService;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取数据
|
* 获取数据
|
||||||
*/
|
*/
|
||||||
@ModelAttribute
|
@ModelAttribute
|
||||||
public MyProjectTask get(String taskId, boolean isNewRecord) {
|
public MyProjectTask get(String taskId, boolean isNewRecord) {
|
||||||
return myProjectTaskService.get(taskId, isNewRecord);
|
return myProjectTaskService.get(taskId, isNewRecord);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询列表
|
* 查询列表
|
||||||
*/
|
*/
|
||||||
@RequiresPermissions("biz:myProjectTask:view")
|
@RequiresPermissions("biz:myProjectTask:view")
|
||||||
@RequestMapping(value = {"list", ""})
|
@RequestMapping(value = {"list", ""})
|
||||||
public String list(MyProjectTask myProjectTask, Model model) {
|
public String list(MyProjectTask myProjectTask, Model model) {
|
||||||
model.addAttribute("myProjectTask", myProjectTask);
|
model.addAttribute("myProjectTask", myProjectTask);
|
||||||
return "modules/biz/myProjectTaskList";
|
return "modules/biz/myProjectTaskList";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询列表数据
|
* 查询列表数据
|
||||||
*/
|
*/
|
||||||
@RequiresPermissions("biz:myProjectTask:view")
|
@RequiresPermissions("biz:myProjectTask:view")
|
||||||
@RequestMapping(value = "listData")
|
@RequestMapping(value = "listData")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public Page<MyProjectTask> listData(MyProjectTask myProjectTask, HttpServletRequest request, HttpServletResponse response) {
|
public Page<MyProjectTask> listData(MyProjectTask myProjectTask, HttpServletRequest request, HttpServletResponse response) {
|
||||||
myProjectTask.setPage(new Page<>(request, response));
|
myProjectTask.setPage(new Page<>(request, response));
|
||||||
Page<MyProjectTask> page = myProjectTaskService.findPage(myProjectTask);
|
Page<MyProjectTask> page = myProjectTaskService.findPage(myProjectTask);
|
||||||
return page;
|
return page;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查看编辑表单
|
* 查看编辑表单
|
||||||
*/
|
*/
|
||||||
@RequiresPermissions("biz:myProjectTask:view")
|
@RequiresPermissions("biz:myProjectTask:view")
|
||||||
@RequestMapping(value = "form")
|
@RequestMapping(value = "form")
|
||||||
public String form(MyProjectTask myProjectTask, Model model) {
|
public String form(MyProjectTask myProjectTask, Model model) {
|
||||||
model.addAttribute("myProjectTask", myProjectTask);
|
model.addAttribute("myProjectTask", myProjectTask);
|
||||||
return "modules/biz/myProjectTaskForm";
|
return "modules/biz/myProjectTaskForm";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 保存数据
|
* 保存数据
|
||||||
*/
|
*/
|
||||||
@RequiresPermissions("biz:myProjectTask:edit")
|
@RequiresPermissions("biz:myProjectTask:edit")
|
||||||
@PostMapping(value = "save")
|
@PostMapping(value = "save")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public String save(@Validated MyProjectTask myProjectTask) {
|
public String save(@Validated MyProjectTask myProjectTask) {
|
||||||
myProjectTaskService.save(myProjectTask);
|
myProjectTaskService.save(myProjectTask);
|
||||||
return renderResult(Global.TRUE, text("保存任务成功!"));
|
return renderResult(Global.TRUE, text("保存任务成功!"));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 导出数据
|
* 导出数据
|
||||||
*/
|
*/
|
||||||
@RequiresPermissions("biz:myProjectTask:view")
|
@RequiresPermissions("biz:myProjectTask:view")
|
||||||
@RequestMapping(value = "exportData")
|
@RequestMapping(value = "exportData")
|
||||||
public void exportData(MyProjectTask myProjectTask, HttpServletResponse response) {
|
public void exportData(MyProjectTask myProjectTask, HttpServletResponse response) {
|
||||||
List<MyProjectTask> list = myProjectTaskService.findList(myProjectTask);
|
List<MyProjectTask> list = myProjectTaskService.findList(myProjectTask);
|
||||||
String fileName = "任务" + DateUtils.getDate("yyyyMMddHHmmss") + ".xlsx";
|
String fileName = "任务" + DateUtils.getDate("yyyyMMddHHmmss") + ".xlsx";
|
||||||
try(ExcelExport ee = new ExcelExport("任务", MyProjectTask.class)){
|
try (ExcelExport ee = new ExcelExport("任务", MyProjectTask.class)) {
|
||||||
ee.setDataList(list).write(response, fileName);
|
ee.setDataList(list).write(response, fileName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 下载模板
|
* 下载模板
|
||||||
*/
|
*/
|
||||||
@RequiresPermissions("biz:myProjectTask:view")
|
@RequiresPermissions("biz:myProjectTask:view")
|
||||||
@RequestMapping(value = "importTemplate")
|
@RequestMapping(value = "importTemplate")
|
||||||
public void importTemplate(HttpServletResponse response) {
|
public void importTemplate(HttpServletResponse response) {
|
||||||
MyProjectTask myProjectTask = new MyProjectTask();
|
MyProjectTask myProjectTask = new MyProjectTask();
|
||||||
List<MyProjectTask> list = ListUtils.newArrayList(myProjectTask);
|
List<MyProjectTask> list = ListUtils.newArrayList(myProjectTask);
|
||||||
String fileName = "任务模板.xlsx";
|
String fileName = "任务模板.xlsx";
|
||||||
try(ExcelExport ee = new ExcelExport("任务", MyProjectTask.class, Type.IMPORT)){
|
try (ExcelExport ee = new ExcelExport("任务", MyProjectTask.class, Type.IMPORT)) {
|
||||||
ee.setDataList(list).write(response, fileName);
|
ee.setDataList(list).write(response, fileName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 导入数据
|
* 导入数据
|
||||||
*/
|
*/
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
@RequiresPermissions("biz:myProjectTask:edit")
|
@RequiresPermissions("biz:myProjectTask:edit")
|
||||||
@PostMapping(value = "importData")
|
@PostMapping(value = "importData")
|
||||||
public String importData(MultipartFile file) {
|
public String importData(MultipartFile file) {
|
||||||
try {
|
try {
|
||||||
String message = myProjectTaskService.importData(file);
|
String message = myProjectTaskService.importData(file);
|
||||||
return renderResult(Global.TRUE, "posfull:"+message);
|
return renderResult(Global.TRUE, "posfull:" + message);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
return renderResult(Global.FALSE, "posfull:"+ex.getMessage());
|
return renderResult(Global.FALSE, "posfull:" + ex.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 删除数据
|
* 删除数据
|
||||||
*/
|
*/
|
||||||
@RequiresPermissions("biz:myProjectTask:edit")
|
@RequiresPermissions("biz:myProjectTask:edit")
|
||||||
@RequestMapping(value = "delete")
|
@RequestMapping(value = "delete")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public String delete(MyProjectTask myProjectTask) {
|
public String delete(MyProjectTask myProjectTask) {
|
||||||
myProjectTaskService.delete(myProjectTask);
|
myProjectTaskService.delete(myProjectTask);
|
||||||
return renderResult(Global.TRUE, text("删除任务成功!"));
|
return renderResult(Global.TRUE, text("删除任务成功!"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@RequestMapping(value = "listAll")
|
||||||
|
@ResponseBody
|
||||||
|
public List<MyProjectTask> listAll(MyProjectTask myProjectTask) {
|
||||||
|
return myProjectTaskService.findList(myProjectTask);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
@jeesite:registry=https://maven.jeesite.net/repository/npm-package/
|
|
||||||
registry=https://registry.npmmirror.com
|
|
||||||
package-manager-strict=false
|
|
||||||
auto-install-peers = true
|
|
||||||
git-checks=false
|
|
||||||
@@ -35,6 +35,9 @@ export interface MyProjectContract extends BasicModel<MyProjectContract> {
|
|||||||
export const myProjectContractList = (params?: MyProjectContract | any) =>
|
export const myProjectContractList = (params?: MyProjectContract | any) =>
|
||||||
defHttp.get<MyProjectContract>({ url: adminPath + '/biz/myProjectContract/list', params });
|
defHttp.get<MyProjectContract>({ url: adminPath + '/biz/myProjectContract/list', params });
|
||||||
|
|
||||||
|
export const myProjectContractListAll = (params?: MyProjectContract | any) =>
|
||||||
|
defHttp.get<MyProjectContract[]>({ url: adminPath + '/biz/myProjectContract/listAll', params });
|
||||||
|
|
||||||
export const myProjectContractListData = (params?: MyProjectContract | any) =>
|
export const myProjectContractListData = (params?: MyProjectContract | any) =>
|
||||||
defHttp.post<Page<MyProjectContract>>({ url: adminPath + '/biz/myProjectContract/listData', params });
|
defHttp.post<Page<MyProjectContract>>({ url: adminPath + '/biz/myProjectContract/listData', params });
|
||||||
|
|
||||||
|
|||||||
@@ -33,6 +33,9 @@ export interface MyProjectTask extends BasicModel<MyProjectTask> {
|
|||||||
export const myProjectTaskList = (params?: MyProjectTask | any) =>
|
export const myProjectTaskList = (params?: MyProjectTask | any) =>
|
||||||
defHttp.get<MyProjectTask>({ url: adminPath + '/biz/myProjectTask/list', params });
|
defHttp.get<MyProjectTask>({ url: adminPath + '/biz/myProjectTask/list', params });
|
||||||
|
|
||||||
|
export const myProjectTaskListAll = (params?: MyProjectTask | any) =>
|
||||||
|
defHttp.get<MyProjectTask[]>({ url: adminPath + '/biz/myProjectTask/listAll', params });
|
||||||
|
|
||||||
export const myProjectTaskListData = (params?: MyProjectTask | any) =>
|
export const myProjectTaskListData = (params?: MyProjectTask | any) =>
|
||||||
defHttp.post<Page<MyProjectTask>>({ url: adminPath + '/biz/myProjectTask/listData', params });
|
defHttp.post<Page<MyProjectTask>>({ url: adminPath + '/biz/myProjectTask/listData', params });
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,11 @@
|
|||||||
import { Icon } from '@jeesite/core/components/Icon';
|
import { Icon } from '@jeesite/core/components/Icon';
|
||||||
import { BasicForm, FormSchema, useForm } from '@jeesite/core/components/Form';
|
import { BasicForm, FormSchema, useForm } from '@jeesite/core/components/Form';
|
||||||
import { BasicDrawer, useDrawerInner } from '@jeesite/core/components/Drawer';
|
import { BasicDrawer, useDrawerInner } from '@jeesite/core/components/Drawer';
|
||||||
import { MyProjectRequirement, myProjectRequirementSave, myProjectRequirementForm } from '@jeesite/biz/api/biz/myProjectRequirement';
|
import {
|
||||||
|
MyProjectRequirement,
|
||||||
|
myProjectRequirementSave,
|
||||||
|
myProjectRequirementForm,
|
||||||
|
} from '@jeesite/biz/api/biz/myProjectRequirement';
|
||||||
import { formatToDateTime } from '@jeesite/core/utils/dateUtil';
|
import { formatToDateTime } from '@jeesite/core/utils/dateUtil';
|
||||||
import { useUserStore } from '@jeesite/core/store/modules/user';
|
import { useUserStore } from '@jeesite/core/store/modules/user';
|
||||||
|
|
||||||
@@ -46,6 +50,10 @@
|
|||||||
value: record.value.isNewRecord ? t('新增需求') : t('编辑需求'),
|
value: record.value.isNewRecord ? t('新增需求') : t('编辑需求'),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
function getRequirementNo() {
|
||||||
|
return `WS_${Date.now()}`;
|
||||||
|
}
|
||||||
|
|
||||||
const inputFormSchemas: FormSchema<MyProjectRequirement>[] = [
|
const inputFormSchemas: FormSchema<MyProjectRequirement>[] = [
|
||||||
{
|
{
|
||||||
label: t('基本信息'),
|
label: t('基本信息'),
|
||||||
@@ -59,6 +67,7 @@
|
|||||||
component: 'Input',
|
component: 'Input',
|
||||||
componentProps: {
|
componentProps: {
|
||||||
maxlength: 64,
|
maxlength: 64,
|
||||||
|
disabled: true,
|
||||||
},
|
},
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
@@ -74,38 +83,38 @@
|
|||||||
{
|
{
|
||||||
label: t('项目名称'),
|
label: t('项目名称'),
|
||||||
field: 'projectId',
|
field: 'projectId',
|
||||||
fieldLabel: 'projectName',
|
fieldLabel: 'projectName',
|
||||||
component: 'ListSelect',
|
component: 'ListSelect',
|
||||||
componentProps: {
|
componentProps: {
|
||||||
selectType: 'bizProjectSelect',
|
selectType: 'bizProjectSelect',
|
||||||
},
|
},
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: t('优先等级'),
|
||||||
|
field: 'priority',
|
||||||
|
component: 'Select',
|
||||||
|
componentProps: {
|
||||||
|
dictType: 'biz_priority',
|
||||||
|
allowClear: true,
|
||||||
|
},
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
label: t('优先等级'),
|
|
||||||
field: 'priority',
|
|
||||||
component: 'Select',
|
|
||||||
componentProps: {
|
|
||||||
dictType: 'biz_priority',
|
|
||||||
allowClear: true,
|
|
||||||
},
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
label: t('详细内容'),
|
label: t('详细内容'),
|
||||||
field: 'requirementContent',
|
field: 'requirementContent',
|
||||||
component: 'InputTextArea',
|
component: 'InputTextArea',
|
||||||
required: true,
|
required: true,
|
||||||
colProps: { md: 24, lg: 24 },
|
colProps: { md: 24, lg: 24 },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('需求状态'),
|
label: t('需求状态'),
|
||||||
field: 'requirementStatus',
|
field: 'requirementStatus',
|
||||||
component: 'Select',
|
component: 'Select',
|
||||||
componentProps: {
|
componentProps: {
|
||||||
dictType: 'requirement_status',
|
dictType: 'requirement_status',
|
||||||
allowClear: true,
|
allowClear: true,
|
||||||
},
|
},
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -138,7 +147,7 @@
|
|||||||
label: t('需求备注'),
|
label: t('需求备注'),
|
||||||
field: 'remark',
|
field: 'remark',
|
||||||
component: 'InputTextArea',
|
component: 'InputTextArea',
|
||||||
colProps: { md: 24, lg: 24 },
|
colProps: { md: 24, lg: 24 },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('附件上传'),
|
label: t('附件上传'),
|
||||||
@@ -165,6 +174,9 @@
|
|||||||
await resetFields();
|
await resetFields();
|
||||||
const res = await myProjectRequirementForm(data);
|
const res = await myProjectRequirementForm(data);
|
||||||
record.value = (res.myProjectRequirement || {}) as MyProjectRequirement;
|
record.value = (res.myProjectRequirement || {}) as MyProjectRequirement;
|
||||||
|
if (record.value.isNewRecord) {
|
||||||
|
record.value.requirementNo = getRequirementNo();
|
||||||
|
}
|
||||||
record.value.__t = new Date().getTime();
|
record.value.__t = new Date().getTime();
|
||||||
await setFieldsValue(record.value);
|
await setFieldsValue(record.value);
|
||||||
setDrawerProps({ loading: false });
|
setDrawerProps({ loading: false });
|
||||||
@@ -179,11 +191,12 @@
|
|||||||
requirementId: record.value.requirementId || data.requirementId,
|
requirementId: record.value.requirementId || data.requirementId,
|
||||||
};
|
};
|
||||||
|
|
||||||
if(record.value.isNewRecord){
|
if (record.value.isNewRecord) {
|
||||||
data.createUser = userinfo.value.loginCode;
|
data.createUser = userinfo.value.loginCode;
|
||||||
}
|
data.requirementNo = getRequirementNo();
|
||||||
|
}
|
||||||
|
|
||||||
data[record.value.isNewRecord ? 'createTime' : 'updateTime'] = formatToDateTime(new Date());
|
data[record.value.isNewRecord ? 'createTime' : 'updateTime'] = formatToDateTime(new Date());
|
||||||
|
|
||||||
// console.log('submit', params, data, record);
|
// console.log('submit', params, data, record);
|
||||||
const res = await myProjectRequirementSave(params, data);
|
const res = await myProjectRequirementSave(params, data);
|
||||||
|
|||||||
@@ -1,186 +0,0 @@
|
|||||||
import { useI18n } from '@jeesite/core/hooks/web/useI18n';
|
|
||||||
import { BasicColumn, BasicTableProps, FormProps } from '@jeesite/core/components/Table';
|
|
||||||
import { myProjectRequirementListData } from '@jeesite/biz/api/biz/myProjectRequirement';
|
|
||||||
|
|
||||||
const { t } = useI18n('biz.myProjectRequirement');
|
|
||||||
|
|
||||||
const modalProps = {
|
|
||||||
title: t('需求选择'),
|
|
||||||
};
|
|
||||||
|
|
||||||
const searchForm: FormProps<MyProjectRequirement> = {
|
|
||||||
baseColProps: { md: 8, lg: 6 },
|
|
||||||
labelWidth: 90,
|
|
||||||
schemas: [
|
|
||||||
{
|
|
||||||
label: t('记录时间起'),
|
|
||||||
field: 'createTime_gte',
|
|
||||||
component: 'DatePicker',
|
|
||||||
componentProps: {
|
|
||||||
format: 'YYYY-MM-DD HH:mm',
|
|
||||||
showTime: { format: 'HH:mm' },
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: t('记录时间止'),
|
|
||||||
field: 'createTime_lte',
|
|
||||||
component: 'DatePicker',
|
|
||||||
componentProps: {
|
|
||||||
format: 'YYYY-MM-DD HH:mm',
|
|
||||||
showTime: { format: 'HH:mm' },
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: t('需求编号'),
|
|
||||||
field: 'requirementNo',
|
|
||||||
component: 'Input',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: t('需求标题'),
|
|
||||||
field: 'requirementTitle',
|
|
||||||
component: 'Input',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: t('项目编号'),
|
|
||||||
field: 'projectId',
|
|
||||||
component: 'Input',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: t('优先等级'),
|
|
||||||
field: 'priority',
|
|
||||||
component: 'Input',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: t('需求状态'),
|
|
||||||
field: 'requirementStatus',
|
|
||||||
component: 'Input',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
const tableColumns: BasicColumn<MyProjectRequirement>[] = [
|
|
||||||
{
|
|
||||||
title: t('记录时间'),
|
|
||||||
dataIndex: 'createTime',
|
|
||||||
key: 'a.create_time',
|
|
||||||
sorter: true,
|
|
||||||
width: 230,
|
|
||||||
align: 'left',
|
|
||||||
slot: 'firstColumn',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t('需求编号'),
|
|
||||||
dataIndex: 'requirementNo',
|
|
||||||
key: 'a.requirement_no',
|
|
||||||
sorter: true,
|
|
||||||
width: 130,
|
|
||||||
align: 'left',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t('需求标题'),
|
|
||||||
dataIndex: 'requirementTitle',
|
|
||||||
key: 'a.requirement_title',
|
|
||||||
sorter: true,
|
|
||||||
width: 130,
|
|
||||||
align: 'left',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t('项目编号'),
|
|
||||||
dataIndex: 'projectId',
|
|
||||||
key: 'a.project_id',
|
|
||||||
sorter: true,
|
|
||||||
width: 130,
|
|
||||||
align: 'left',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t('详细内容'),
|
|
||||||
dataIndex: 'requirementContent',
|
|
||||||
key: 'a.requirement_content',
|
|
||||||
sorter: true,
|
|
||||||
width: 130,
|
|
||||||
align: 'left',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t('优先等级'),
|
|
||||||
dataIndex: 'priority',
|
|
||||||
key: 'a.priority',
|
|
||||||
sorter: true,
|
|
||||||
width: 130,
|
|
||||||
align: 'left',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t('需求状态'),
|
|
||||||
dataIndex: 'requirementStatus',
|
|
||||||
key: 'a.requirement_status',
|
|
||||||
sorter: true,
|
|
||||||
width: 130,
|
|
||||||
align: 'left',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t('负责人员'),
|
|
||||||
dataIndex: 'handler',
|
|
||||||
key: 'a.handler',
|
|
||||||
sorter: true,
|
|
||||||
width: 130,
|
|
||||||
align: 'left',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t('计划完成时间'),
|
|
||||||
dataIndex: 'planFinishTime',
|
|
||||||
key: 'a.plan_finish_time',
|
|
||||||
sorter: true,
|
|
||||||
width: 130,
|
|
||||||
align: 'center',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t('实际完成时间'),
|
|
||||||
dataIndex: 'actualFinishTime',
|
|
||||||
key: 'a.actual_finish_time',
|
|
||||||
sorter: true,
|
|
||||||
width: 130,
|
|
||||||
align: 'center',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t('备注'),
|
|
||||||
dataIndex: 'remark',
|
|
||||||
key: 'a.remark',
|
|
||||||
sorter: true,
|
|
||||||
width: 130,
|
|
||||||
align: 'left',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t('创建人'),
|
|
||||||
dataIndex: 'createUser',
|
|
||||||
key: 'a.create_user',
|
|
||||||
sorter: true,
|
|
||||||
width: 130,
|
|
||||||
align: 'left',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t('更新时间'),
|
|
||||||
dataIndex: 'updateTime',
|
|
||||||
key: 'a.update_time',
|
|
||||||
sorter: true,
|
|
||||||
width: 130,
|
|
||||||
align: 'center',
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const tableProps: BasicTableProps = {
|
|
||||||
api: myProjectRequirementListData,
|
|
||||||
beforeFetch: (params) => {
|
|
||||||
params['isAll'] = true;
|
|
||||||
return params;
|
|
||||||
},
|
|
||||||
columns: tableColumns,
|
|
||||||
formConfig: searchForm,
|
|
||||||
rowKey: 'requirementId',
|
|
||||||
};
|
|
||||||
|
|
||||||
export default {
|
|
||||||
modalProps,
|
|
||||||
tableProps,
|
|
||||||
itemCode: 'requirementId',
|
|
||||||
itemName: 'requirementId',
|
|
||||||
isShowCode: false,
|
|
||||||
};
|
|
||||||
@@ -42,7 +42,7 @@
|
|||||||
const { meta } = unref(router.currentRoute);
|
const { meta } = unref(router.currentRoute);
|
||||||
const record = ref<MyProjectTask>({} as MyProjectTask);
|
const record = ref<MyProjectTask>({} as MyProjectTask);
|
||||||
|
|
||||||
const requirementListParams = ref<Recordable>({ projectId: '-1' });
|
const requirementListParams = ref<Recordable>({ projectId: '-1',requirementStatus: '2' });
|
||||||
|
|
||||||
const getTitle = computed(() => ({
|
const getTitle = computed(() => ({
|
||||||
icon: meta.icon || 'i-ant-design:book-outlined',
|
icon: meta.icon || 'i-ant-design:book-outlined',
|
||||||
|
|||||||
@@ -1,194 +0,0 @@
|
|||||||
import { useI18n } from '@jeesite/core/hooks/web/useI18n';
|
|
||||||
import { BasicColumn, BasicTableProps, FormProps } from '@jeesite/core/components/Table';
|
|
||||||
import { myProjectTaskListData } from '@jeesite/biz/api/biz/myProjectTask';
|
|
||||||
|
|
||||||
const { t } = useI18n('biz.myProjectTask');
|
|
||||||
|
|
||||||
const modalProps = {
|
|
||||||
title: t('任务选择'),
|
|
||||||
};
|
|
||||||
|
|
||||||
const searchForm: FormProps<MyProjectTask> = {
|
|
||||||
baseColProps: { md: 8, lg: 6 },
|
|
||||||
labelWidth: 90,
|
|
||||||
schemas: [
|
|
||||||
{
|
|
||||||
label: t('记录时间起'),
|
|
||||||
field: 'createTime_gte',
|
|
||||||
component: 'DatePicker',
|
|
||||||
componentProps: {
|
|
||||||
format: 'YYYY-MM-DD HH:mm',
|
|
||||||
showTime: { format: 'HH:mm' },
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: t('记录时间止'),
|
|
||||||
field: 'createTime_lte',
|
|
||||||
component: 'DatePicker',
|
|
||||||
componentProps: {
|
|
||||||
format: 'YYYY-MM-DD HH:mm',
|
|
||||||
showTime: { format: 'HH:mm' },
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: t('任务名称'),
|
|
||||||
field: 'taskName',
|
|
||||||
component: 'Input',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: t('项目标识'),
|
|
||||||
field: 'projectId',
|
|
||||||
component: 'Input',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: t('需求标识'),
|
|
||||||
field: 'requirementId',
|
|
||||||
component: 'Input',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: t('任务状态'),
|
|
||||||
field: 'taskStatus',
|
|
||||||
component: 'Input',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: t('备注'),
|
|
||||||
field: 'remark',
|
|
||||||
component: 'Input',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
const tableColumns: BasicColumn<MyProjectTask>[] = [
|
|
||||||
{
|
|
||||||
title: t('记录时间'),
|
|
||||||
dataIndex: 'createTime',
|
|
||||||
key: 'a.create_time',
|
|
||||||
sorter: true,
|
|
||||||
width: 230,
|
|
||||||
align: 'left',
|
|
||||||
slot: 'firstColumn',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t('任务名称'),
|
|
||||||
dataIndex: 'taskName',
|
|
||||||
key: 'a.task_name',
|
|
||||||
sorter: true,
|
|
||||||
width: 130,
|
|
||||||
align: 'left',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t('项目标识'),
|
|
||||||
dataIndex: 'projectId',
|
|
||||||
key: 'a.project_id',
|
|
||||||
sorter: true,
|
|
||||||
width: 130,
|
|
||||||
align: 'left',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t('需求标识'),
|
|
||||||
dataIndex: 'requirementId',
|
|
||||||
key: 'a.requirement_id',
|
|
||||||
sorter: true,
|
|
||||||
width: 130,
|
|
||||||
align: 'left',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t('任务状态'),
|
|
||||||
dataIndex: 'taskStatus',
|
|
||||||
key: 'a.task_status',
|
|
||||||
sorter: true,
|
|
||||||
width: 130,
|
|
||||||
align: 'left',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t('负责人员'),
|
|
||||||
dataIndex: 'handler',
|
|
||||||
key: 'a.handler',
|
|
||||||
sorter: true,
|
|
||||||
width: 130,
|
|
||||||
align: 'left',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t('计划开始'),
|
|
||||||
dataIndex: 'planStartTime',
|
|
||||||
key: 'a.plan_start_time',
|
|
||||||
sorter: true,
|
|
||||||
width: 130,
|
|
||||||
align: 'center',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t('计划结束'),
|
|
||||||
dataIndex: 'planEndTime',
|
|
||||||
key: 'a.plan_end_time',
|
|
||||||
sorter: true,
|
|
||||||
width: 130,
|
|
||||||
align: 'center',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t('实际开始'),
|
|
||||||
dataIndex: 'actualStartTime',
|
|
||||||
key: 'a.actual_start_time',
|
|
||||||
sorter: true,
|
|
||||||
width: 130,
|
|
||||||
align: 'center',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t('实际结束'),
|
|
||||||
dataIndex: 'actualEndTime',
|
|
||||||
key: 'a.actual_end_time',
|
|
||||||
sorter: true,
|
|
||||||
width: 130,
|
|
||||||
align: 'center',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t('工时'),
|
|
||||||
dataIndex: 'workHours',
|
|
||||||
key: 'a.work_hours',
|
|
||||||
sorter: true,
|
|
||||||
width: 130,
|
|
||||||
align: 'right',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t('备注'),
|
|
||||||
dataIndex: 'remark',
|
|
||||||
key: 'a.remark',
|
|
||||||
sorter: true,
|
|
||||||
width: 130,
|
|
||||||
align: 'left',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t('创建人员'),
|
|
||||||
dataIndex: 'createUser',
|
|
||||||
key: 'a.create_user',
|
|
||||||
sorter: true,
|
|
||||||
width: 130,
|
|
||||||
align: 'left',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t('更新时间'),
|
|
||||||
dataIndex: 'updateTime',
|
|
||||||
key: 'a.update_time',
|
|
||||||
sorter: true,
|
|
||||||
width: 130,
|
|
||||||
align: 'center',
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const tableProps: BasicTableProps = {
|
|
||||||
api: myProjectTaskListData,
|
|
||||||
beforeFetch: (params) => {
|
|
||||||
params['isAll'] = true;
|
|
||||||
return params;
|
|
||||||
},
|
|
||||||
columns: tableColumns,
|
|
||||||
formConfig: searchForm,
|
|
||||||
rowKey: 'taskId',
|
|
||||||
};
|
|
||||||
|
|
||||||
export default {
|
|
||||||
modalProps,
|
|
||||||
tableProps,
|
|
||||||
itemCode: 'taskId',
|
|
||||||
itemName: 'taskId',
|
|
||||||
isShowCode: false,
|
|
||||||
};
|
|
||||||
@@ -1,58 +1,78 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="my-screen-page">
|
<PageWrapper :contentFullHeight="true" :dense="true" title="false" contentClass="my-screen-page-wrapper">
|
||||||
<header class="my-screen-panel my-screen-panel--header">
|
<div class="my-screen-page">
|
||||||
<ChartTop />
|
<header class="my-screen-panel my-screen-panel--header">
|
||||||
</header>
|
<ChartTop />
|
||||||
<section class="my-screen-bottom">
|
</header>
|
||||||
<div class="my-screen-left">
|
<section class="my-screen-bottom">
|
||||||
<section class="my-screen-panel my-screen-left-top">左上区域</section>
|
<div class="my-screen-left">
|
||||||
<section class="my-screen-left-middle">
|
<section class="my-screen-panel my-screen-left-top">左上区域</section>
|
||||||
<div class="my-screen-panel">左中左区域</div>
|
<section class="my-screen-left-middle">
|
||||||
<div class="my-screen-panel">左中右区域</div>
|
<div class="my-screen-panel">左中左区域</div>
|
||||||
</section>
|
<div class="my-screen-panel">左中右区域</div>
|
||||||
<section class="my-screen-left-bottom">
|
</section>
|
||||||
<div class="my-screen-panel">左下左区域</div>
|
<section class="my-screen-left-bottom">
|
||||||
<div class="my-screen-panel">左下右区域</div>
|
<div class="my-screen-panel">左下左区域</div>
|
||||||
</section>
|
<div class="my-screen-panel">左下右区域</div>
|
||||||
</div>
|
</section>
|
||||||
<aside class="my-screen-right">
|
</div>
|
||||||
<section class="my-screen-panel my-screen-right-top">右上区域</section>
|
<aside class="my-screen-right">
|
||||||
<section class="my-screen-panel my-screen-right-middle">右中区域</section>
|
<section class="my-screen-panel my-screen-right-top">右上区域</section>
|
||||||
<section class="my-screen-panel my-screen-right-bottom">右下区域</section>
|
<section class="my-screen-panel my-screen-right-middle">右中区域</section>
|
||||||
</aside>
|
<section class="my-screen-panel my-screen-right-bottom">右下区域</section>
|
||||||
</section>
|
</aside>
|
||||||
</div>
|
</section>
|
||||||
|
</div>
|
||||||
|
</PageWrapper>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup name="BizMyScreen">
|
<script lang="ts" setup name="BizMyScreen">
|
||||||
import ChartTop from './components/ChartTop.vue';
|
import { PageWrapper } from '@jeesite/core/components/Page';
|
||||||
|
import ChartTop from './components/ChartTop.vue';
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
@dark-bg: #141414;
|
@dark-bg: #141414;
|
||||||
|
@desktop-page-gap: 12px;
|
||||||
|
@desktop-page-padding: 0;
|
||||||
|
@desktop-card-radius: 10px;
|
||||||
|
@desktop-card-border: 1px solid rgb(226 232 240);
|
||||||
|
@desktop-card-shadow: 0 1px 3px rgb(15 23 42 / 0.06);
|
||||||
|
@desktop-dark-border: rgb(51 65 85);
|
||||||
|
|
||||||
|
.my-screen-page-wrapper {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
height: 100%;
|
||||||
|
min-height: 0;
|
||||||
|
padding: 0 !important;
|
||||||
|
overflow: hidden !important;
|
||||||
|
background: transparent !important;
|
||||||
|
}
|
||||||
|
|
||||||
.my-screen-page {
|
.my-screen-page {
|
||||||
|
display: flex;
|
||||||
|
flex: 1;
|
||||||
|
flex-direction: column;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
display: flex;
|
gap: @desktop-page-gap;
|
||||||
flex-direction: column;
|
padding: @desktop-page-padding;
|
||||||
gap: 12px;
|
|
||||||
padding: 0;
|
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
border-radius: 10px;
|
border-radius: @desktop-card-radius;
|
||||||
}
|
}
|
||||||
|
|
||||||
.my-screen-panel {
|
.my-screen-panel {
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
padding: 8px 12px 12px;
|
padding: 8px 12px 12px;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
border-radius: 10px;
|
border-radius: @desktop-card-radius;
|
||||||
border: 1px solid rgb(226 232 240);
|
border: @desktop-card-border;
|
||||||
background: rgb(255, 255, 255);
|
background: rgb(255, 255, 255);
|
||||||
box-shadow: 0 1px 3px rgb(15 23 42 / 0.06);
|
box-shadow: @desktop-card-shadow;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
@@ -72,9 +92,9 @@
|
|||||||
flex: 1 1 90%;
|
flex: 1 1 90%;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 12px;
|
gap: @desktop-page-gap;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
border-radius: 10px;
|
border-radius: @desktop-card-radius;
|
||||||
}
|
}
|
||||||
|
|
||||||
.my-screen-left {
|
.my-screen-left {
|
||||||
@@ -83,7 +103,7 @@
|
|||||||
min-height: 0;
|
min-height: 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 12px;
|
gap: @desktop-page-gap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.my-screen-right {
|
.my-screen-right {
|
||||||
@@ -92,7 +112,7 @@
|
|||||||
min-height: 0;
|
min-height: 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 12px;
|
gap: @desktop-page-gap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.my-screen-left-top {
|
.my-screen-left-top {
|
||||||
@@ -104,7 +124,7 @@
|
|||||||
flex: 1 1 0;
|
flex: 1 1 0;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 12px;
|
gap: @desktop-page-gap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.my-screen-left-middle .my-screen-panel,
|
.my-screen-left-middle .my-screen-panel,
|
||||||
@@ -131,9 +151,8 @@
|
|||||||
background: @dark-bg !important;
|
background: @dark-bg !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
html[data-theme='dark'] .my-screen-panel,
|
|
||||||
html[data-theme='dark'] .my-screen-panel {
|
html[data-theme='dark'] .my-screen-panel {
|
||||||
border-color: rgb(51 65 85);
|
border-color: @desktop-dark-border;
|
||||||
background: @dark-bg !important;
|
background: @dark-bg !important;
|
||||||
color: rgb(203 213 225);
|
color: rgb(203 213 225);
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
@@ -145,8 +164,9 @@
|
|||||||
|
|
||||||
@media (max-width: 768px) {
|
@media (max-width: 768px) {
|
||||||
.my-screen-page {
|
.my-screen-page {
|
||||||
height: auto;
|
flex: 1 1 auto;
|
||||||
min-height: 100%;
|
height: 100%;
|
||||||
|
min-height: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.my-screen-panel--header {
|
.my-screen-panel--header {
|
||||||
|
|||||||
@@ -93,19 +93,22 @@
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const loadComponent = (vueName: string) => {
|
const loadComponent = (vueName: string): Component => {
|
||||||
return defineAsyncComponent({
|
return defineAsyncComponent({
|
||||||
loader: () => import(`./components/${vueName}.vue`),
|
loader: () => import(`./components/${vueName}.vue`),
|
||||||
delay: 200,
|
delay: 200,
|
||||||
timeout: 5000,
|
timeout: 5000,
|
||||||
|
onError(error) {
|
||||||
|
console.error('加载组件失败', error);
|
||||||
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
async function getChartList() {
|
async function getChartList() {
|
||||||
try {
|
try {
|
||||||
const reqParams = {
|
const reqParams = {
|
||||||
ustatus: '1',
|
ustatus: '1',
|
||||||
chartCode: 'erp',
|
chartCode: 'erp',
|
||||||
};
|
};
|
||||||
const res = await myChartInfoListAll(reqParams);
|
const res = await myChartInfoListAll(reqParams);
|
||||||
chartData.value = res || [];
|
chartData.value = res || [];
|
||||||
@@ -132,7 +135,9 @@
|
|||||||
await getChartList();
|
await getChartList();
|
||||||
|
|
||||||
const newComponentMap: ComponentMap = {};
|
const newComponentMap: ComponentMap = {};
|
||||||
const uniqueComponents = [...new Set(chartData.value.map((item) => item.vueName))];
|
const uniqueComponents = [...new Set(chartData.value.map((item) => item.vueName))].filter(
|
||||||
|
(vueName) => vueName && vueName !== 'ChartTop',
|
||||||
|
);
|
||||||
for (const vueName of uniqueComponents) {
|
for (const vueName of uniqueComponents) {
|
||||||
if (vueName) {
|
if (vueName) {
|
||||||
newComponentMap[vueName] = loadComponent(vueName);
|
newComponentMap[vueName] = loadComponent(vueName);
|
||||||
|
|||||||
@@ -29,7 +29,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref, watch, onMounted } from 'vue';
|
import { ref, watch, onMounted, defineAsyncComponent } from 'vue';
|
||||||
import type { Component } from 'vue';
|
import type { Component } from 'vue';
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
import ChartTop from './components/ChartTop.vue';
|
import ChartTop from './components/ChartTop.vue';
|
||||||
@@ -68,21 +68,22 @@
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const loadComponent = async (vueName: string): Promise<Component | null> => {
|
const loadComponent = (vueName: string): Component => {
|
||||||
try {
|
return defineAsyncComponent({
|
||||||
const module = await import(`./components/${vueName}.vue`);
|
loader: () => import(`./components/${vueName}.vue`),
|
||||||
return module.default;
|
delay: 200,
|
||||||
} catch (error) {
|
timeout: 5000,
|
||||||
console.error('加载组件失败', error);
|
onError(error) {
|
||||||
return null;
|
console.error('加载组件失败', error);
|
||||||
}
|
},
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
async function getChartList() {
|
async function getChartList() {
|
||||||
try {
|
try {
|
||||||
const reqParams = {
|
const reqParams = {
|
||||||
ustatus: '1',
|
ustatus: '1',
|
||||||
chartCode: 'home',
|
chartCode: 'home',
|
||||||
};
|
};
|
||||||
const res = await myChartInfoListAll(reqParams);
|
const res = await myChartInfoListAll(reqParams);
|
||||||
chartData.value = res || [];
|
chartData.value = res || [];
|
||||||
@@ -97,7 +98,9 @@
|
|||||||
await getChartList();
|
await getChartList();
|
||||||
|
|
||||||
const newComponentMap: ComponentMap = {};
|
const newComponentMap: ComponentMap = {};
|
||||||
const uniqueComponents = [...new Set(chartData.value.map((item) => item.vueName))];
|
const uniqueComponents = [...new Set(chartData.value.map((item) => item.vueName))].filter(
|
||||||
|
(vueName) => vueName && vueName !== 'ChartTop',
|
||||||
|
);
|
||||||
for (const vueName of uniqueComponents) {
|
for (const vueName of uniqueComponents) {
|
||||||
if (vueName) {
|
if (vueName) {
|
||||||
newComponentMap[vueName] = loadComponent(vueName);
|
newComponentMap[vueName] = loadComponent(vueName);
|
||||||
|
|||||||
@@ -29,7 +29,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref, watch, onMounted } from 'vue';
|
import { ref, watch, onMounted, defineAsyncComponent } from 'vue';
|
||||||
import type { Component } from 'vue';
|
import type { Component } from 'vue';
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
import ChartTop from './components/ChartTop.vue';
|
import ChartTop from './components/ChartTop.vue';
|
||||||
@@ -68,21 +68,22 @@
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const loadComponent = async (vueName: string): Promise<Component | null> => {
|
const loadComponent = (vueName: string): Component => {
|
||||||
try {
|
return defineAsyncComponent({
|
||||||
const module = await import(`./components/${vueName}.vue`);
|
loader: () => import(`./components/${vueName}.vue`),
|
||||||
return module.default;
|
delay: 200,
|
||||||
} catch (error) {
|
timeout: 5000,
|
||||||
console.error('加载组件失败', error);
|
onError(error) {
|
||||||
return null;
|
console.error('加载组件失败', error);
|
||||||
}
|
},
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
async function getChartList() {
|
async function getChartList() {
|
||||||
try {
|
try {
|
||||||
const reqParams = {
|
const reqParams = {
|
||||||
ustatus: '1',
|
ustatus: '1',
|
||||||
chartCode: 'sys',
|
chartCode: 'sys',
|
||||||
};
|
};
|
||||||
const res = await myChartInfoListAll(reqParams);
|
const res = await myChartInfoListAll(reqParams);
|
||||||
chartData.value = res || [];
|
chartData.value = res || [];
|
||||||
@@ -97,7 +98,9 @@
|
|||||||
await getChartList();
|
await getChartList();
|
||||||
|
|
||||||
const newComponentMap: ComponentMap = {};
|
const newComponentMap: ComponentMap = {};
|
||||||
const uniqueComponents = [...new Set(chartData.value.map((item) => item.vueName))];
|
const uniqueComponents = [...new Set(chartData.value.map((item) => item.vueName))].filter(
|
||||||
|
(vueName) => vueName && vueName !== 'ChartTop',
|
||||||
|
);
|
||||||
for (const vueName of uniqueComponents) {
|
for (const vueName of uniqueComponents) {
|
||||||
if (vueName) {
|
if (vueName) {
|
||||||
newComponentMap[vueName] = loadComponent(vueName);
|
newComponentMap[vueName] = loadComponent(vueName);
|
||||||
|
|||||||
@@ -37,7 +37,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref, watch, onMounted } from 'vue';
|
import { ref, watch, onMounted, defineAsyncComponent } from 'vue';
|
||||||
import type { Component } from 'vue';
|
import type { Component } from 'vue';
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
import ChartTop from './components/ChartTop.vue';
|
import ChartTop from './components/ChartTop.vue';
|
||||||
@@ -80,21 +80,22 @@
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const loadComponent = async (vueName: string): Promise<Component | null> => {
|
const loadComponent = (vueName: string): Component => {
|
||||||
try {
|
return defineAsyncComponent({
|
||||||
const module = await import(`./components/${vueName}.vue`);
|
loader: () => import(`./components/${vueName}.vue`),
|
||||||
return module.default;
|
delay: 200,
|
||||||
} catch (error) {
|
timeout: 5000,
|
||||||
console.error('加载组件失败', error);
|
onError(error) {
|
||||||
return null;
|
console.error('加载组件失败', error);
|
||||||
}
|
},
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
async function getChartList() {
|
async function getChartList() {
|
||||||
try {
|
try {
|
||||||
const reqParams = {
|
const reqParams = {
|
||||||
ustatus: '1',
|
ustatus: '1',
|
||||||
chartCode: 'work',
|
chartCode: 'work',
|
||||||
};
|
};
|
||||||
const res = await myChartInfoListAll(reqParams);
|
const res = await myChartInfoListAll(reqParams);
|
||||||
chartData.value = res || [];
|
chartData.value = res || [];
|
||||||
@@ -109,7 +110,9 @@
|
|||||||
await getChartList();
|
await getChartList();
|
||||||
|
|
||||||
const newComponentMap: ComponentMap = {};
|
const newComponentMap: ComponentMap = {};
|
||||||
const uniqueComponents = [...new Set(chartData.value.map((item) => item.vueName))];
|
const uniqueComponents = [...new Set(chartData.value.map((item) => item.vueName))].filter(
|
||||||
|
(vueName) => vueName && vueName !== 'ChartTop',
|
||||||
|
);
|
||||||
for (const vueName of uniqueComponents) {
|
for (const vueName of uniqueComponents) {
|
||||||
if (vueName) {
|
if (vueName) {
|
||||||
newComponentMap[vueName] = loadComponent(vueName);
|
newComponentMap[vueName] = loadComponent(vueName);
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<PageWrapper>
|
<PageWrapper :contentFullHeight="true" :dense="true" title="false" contentClass="about-page-wrapper">
|
||||||
<template #headerContent>
|
<template #headerContent> </template>
|
||||||
|
|
||||||
</template>
|
|
||||||
<div class="jeesite-workbench">
|
<div class="jeesite-workbench">
|
||||||
<div class="workbench-layout">
|
<div class="workbench-layout">
|
||||||
<div class="workbench-top">10% 区域</div>
|
<div class="workbench-top">10% 区域</div>
|
||||||
@@ -14,10 +12,10 @@
|
|||||||
<div class="workbench-col">30% 区域左侧</div>
|
<div class="workbench-col">30% 区域左侧</div>
|
||||||
<div class="workbench-col">30% 区域右侧</div>
|
<div class="workbench-col">30% 区域右侧</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="workbench-row">
|
<div class="workbench-row">
|
||||||
<div class="workbench-col">30% 区域左侧</div>
|
<div class="workbench-col">30% 区域左侧</div>
|
||||||
<div class="workbench-col">30% 区域右侧</div>
|
<div class="workbench-col">30% 区域右侧</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</PageWrapper>
|
</PageWrapper>
|
||||||
@@ -34,28 +32,48 @@
|
|||||||
|
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
@dark-bg: #141414;
|
@dark-bg: #141414;
|
||||||
|
@desktop-page-gap: 12px;
|
||||||
|
@desktop-page-padding: 0;
|
||||||
|
@desktop-card-radius: 10px;
|
||||||
|
@desktop-card-border: 1px solid rgb(226 232 240);
|
||||||
|
@desktop-card-shadow: 0 1px 3px rgb(15 23 42 / 0.06);
|
||||||
|
@desktop-dark-border: rgb(51 65 85);
|
||||||
|
|
||||||
|
.about-page-wrapper {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
height: 100%;
|
||||||
|
min-height: 0;
|
||||||
|
padding: 0 !important;
|
||||||
|
overflow: hidden !important;
|
||||||
|
background: transparent !important;
|
||||||
|
}
|
||||||
|
|
||||||
.jeesite-workbench {
|
.jeesite-workbench {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
flex: 1;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
background: #FFFFFF;
|
background: #ffffff;
|
||||||
border-radius: 10px;
|
border-radius: @desktop-card-radius;
|
||||||
}
|
}
|
||||||
|
|
||||||
.jeesite-workbench .workbench-layout {
|
.jeesite-workbench .workbench-layout {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
flex: 1;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 12px;
|
gap: @desktop-page-gap;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
padding: 4px;
|
padding: @desktop-page-padding;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
border-radius: 10px;
|
border-radius: @desktop-card-radius;
|
||||||
}
|
}
|
||||||
|
|
||||||
.jeesite-workbench .workbench-top {
|
.jeesite-workbench .workbench-top {
|
||||||
@@ -66,7 +84,7 @@
|
|||||||
.jeesite-workbench .workbench-row {
|
.jeesite-workbench .workbench-row {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex: 0 0 30%;
|
flex: 0 0 30%;
|
||||||
gap: 12px;
|
gap: @desktop-page-gap;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,9 +93,10 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
border-radius: 10px;
|
border-radius: @desktop-card-radius;
|
||||||
border: 1px solid rgb(226 232 240);
|
border: @desktop-card-border;
|
||||||
background: #FFFFFF;
|
background: #ffffff;
|
||||||
|
box-shadow: @desktop-card-shadow;
|
||||||
color: rgb(71 85 105);
|
color: rgb(71 85 105);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,8 +113,9 @@
|
|||||||
|
|
||||||
html[data-theme='dark'] .jeesite-workbench .workbench-top,
|
html[data-theme='dark'] .jeesite-workbench .workbench-top,
|
||||||
html[data-theme='dark'] .jeesite-workbench .workbench-col {
|
html[data-theme='dark'] .jeesite-workbench .workbench-col {
|
||||||
border-color: rgb(51 65 85);
|
border-color: @desktop-dark-border;
|
||||||
background: @dark-bg !important;
|
background: @dark-bg !important;
|
||||||
color: rgb(226 232 240);
|
color: rgb(226 232 240);
|
||||||
|
box-shadow: none;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -43,6 +43,10 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
|
@analysis-dark-bg: rgb(20, 20, 20);
|
||||||
|
@analysis-dark-hover-bg: rgb(30 41 59);
|
||||||
|
@analysis-dark-shadow: 0 10px 24px rgb(0 0 0 / 24%);
|
||||||
|
|
||||||
.biz-apps-card {
|
.biz-apps-card {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
@@ -122,7 +126,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
html[data-theme='dark'] .biz-apps-card {
|
html[data-theme='dark'] .biz-apps-card {
|
||||||
background: rgb(20, 20, 20);
|
background: @analysis-dark-bg;
|
||||||
|
|
||||||
.card-title {
|
.card-title {
|
||||||
color: rgb(203 213 225);
|
color: rgb(203 213 225);
|
||||||
@@ -131,12 +135,13 @@
|
|||||||
|
|
||||||
.biz-apps-item {
|
.biz-apps-item {
|
||||||
border-color: rgb(51 65 85);
|
border-color: rgb(51 65 85);
|
||||||
background: rgb(20, 20, 20);
|
background: @analysis-dark-bg;
|
||||||
box-shadow: 0 10px 24px rgb(0 0 0 / 24%);
|
box-shadow: @analysis-dark-shadow;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
border-color: rgb(96 165 250);
|
border-color: rgb(96 165 250);
|
||||||
box-shadow: 0 14px 32px rgb(37 99 235 / 22%);
|
background: @analysis-dark-hover-bg;
|
||||||
|
box-shadow: @analysis-dark-shadow;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__name {
|
&__name {
|
||||||
|
|||||||
@@ -276,6 +276,10 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
|
@analysis-dark-bg: rgb(20, 20, 20);
|
||||||
|
@analysis-dark-hover-bg: rgb(30 41 59);
|
||||||
|
@analysis-dark-shadow: 0 10px 24px rgb(0 0 0 / 24%);
|
||||||
|
|
||||||
.host-card {
|
.host-card {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
@@ -413,7 +417,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
html[data-theme='dark'] .host-card {
|
html[data-theme='dark'] .host-card {
|
||||||
background: rgb(20, 20, 20);
|
background: @analysis-dark-bg;
|
||||||
|
|
||||||
.card-title {
|
.card-title {
|
||||||
color: rgb(203 213 225);
|
color: rgb(203 213 225);
|
||||||
@@ -438,20 +442,21 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.host-gauge-panel {
|
.host-gauge-panel {
|
||||||
background: linear-gradient(180deg, rgb(20, 20, 20) 0%, rgb(28 28 28) 100%);
|
background: @analysis-dark-bg;
|
||||||
box-shadow: 0 10px 24px rgb(0 0 0 / 24%);
|
box-shadow: @analysis-dark-shadow;
|
||||||
}
|
}
|
||||||
|
|
||||||
.metric-item {
|
.metric-item {
|
||||||
background: linear-gradient(180deg, rgb(20, 20, 20) 0%, rgb(28 28 28) 100%);
|
background: @analysis-dark-bg;
|
||||||
box-shadow: 0 10px 24px rgb(0 0 0 / 24%);
|
box-shadow: @analysis-dark-shadow;
|
||||||
|
|
||||||
&__label {
|
&__label {
|
||||||
color: rgb(148 163 184);
|
color: rgb(148 163 184);
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
box-shadow: 0 12px 28px rgb(96 165 250 / 20%);
|
background: @analysis-dark-hover-bg;
|
||||||
|
box-shadow: @analysis-dark-shadow;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -206,7 +206,9 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
@dark-bg: #141414;
|
@analysis-dark-bg: rgb(20, 20, 20);
|
||||||
|
@analysis-dark-hover-bg: rgb(30 41 59);
|
||||||
|
@analysis-dark-shadow: 0 10px 24px rgb(0 0 0 / 24%);
|
||||||
|
|
||||||
.notice-card {
|
.notice-card {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@@ -591,7 +593,7 @@
|
|||||||
|
|
||||||
html[data-theme='dark'] .notice-card {
|
html[data-theme='dark'] .notice-card {
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
background: rgb(20, 20, 20);
|
background: @analysis-dark-bg;
|
||||||
|
|
||||||
.card-title {
|
.card-title {
|
||||||
color: rgb(203 213 225);
|
color: rgb(203 213 225);
|
||||||
@@ -616,15 +618,27 @@
|
|||||||
.table-container {
|
.table-container {
|
||||||
.el-table {
|
.el-table {
|
||||||
--el-table-border-color: transparent;
|
--el-table-border-color: transparent;
|
||||||
--el-table-header-bg-color: rgb(20, 20, 20);
|
--el-table-header-bg-color: @analysis-dark-bg;
|
||||||
--el-table-tr-bg-color: transparent;
|
--el-table-tr-bg-color: transparent;
|
||||||
--el-table-row-hover-bg-color: rgb(30 41 59);
|
--el-table-row-hover-bg-color: @analysis-dark-hover-bg;
|
||||||
--el-table-text-color: rgb(148 163 184);
|
--el-table-text-color: rgb(148 163 184);
|
||||||
--el-table-header-text-color: rgb(226 232 240);
|
--el-table-header-text-color: rgb(226 232 240);
|
||||||
background: transparent;
|
background: transparent;
|
||||||
|
|
||||||
th.el-table__cell {
|
th.el-table__cell {
|
||||||
background: rgb(20, 20, 20);
|
background: @analysis-dark-bg;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-loading-mask {
|
||||||
|
background-color: rgb(20 20 20 / 72%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-loading-spinner .path {
|
||||||
|
stroke: rgb(147 197 253);
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-loading-spinner .el-loading-text {
|
||||||
|
color: rgb(203 213 225);
|
||||||
}
|
}
|
||||||
|
|
||||||
th.el-table__cell,
|
th.el-table__cell,
|
||||||
@@ -650,25 +664,25 @@
|
|||||||
|
|
||||||
&__content-panel,
|
&__content-panel,
|
||||||
&__attachments-panel {
|
&__attachments-panel {
|
||||||
background: rgb(20, 20, 20);
|
background: @analysis-dark-bg;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__attachments-panel {
|
&__attachments-panel {
|
||||||
border-color: rgb(51 65 85);
|
border-color: rgb(51 65 85);
|
||||||
background: rgb(20, 20, 20);
|
background: @analysis-dark-bg;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__content {
|
&__content {
|
||||||
color: rgb(226 232 240);
|
color: rgb(226 232 240);
|
||||||
background: rgb(20, 20, 20);
|
background: @analysis-dark-bg;
|
||||||
border-color: rgb(51 65 85);
|
border-color: rgb(51 65 85);
|
||||||
}
|
}
|
||||||
|
|
||||||
&__attachment-item,
|
&__attachment-item,
|
||||||
&__attachments-empty {
|
&__attachments-empty {
|
||||||
border-color: rgb(71 85 105);
|
border-color: rgb(71 85 105);
|
||||||
background: rgb(20, 20, 20);
|
background: @analysis-dark-bg;
|
||||||
box-shadow: 0 10px 24px rgb(0 0 0 / 24%);
|
box-shadow: @analysis-dark-shadow;
|
||||||
color: rgb(226 232 240);
|
color: rgb(226 232 240);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -686,8 +700,8 @@
|
|||||||
|
|
||||||
&__attachment-item:hover {
|
&__attachment-item:hover {
|
||||||
border-color: rgb(96 165 250);
|
border-color: rgb(96 165 250);
|
||||||
background: rgb(37 99 235 / 22%);
|
background: @analysis-dark-hover-bg;
|
||||||
box-shadow: 0 14px 32px rgb(37 99 235 / 22%);
|
box-shadow: @analysis-dark-shadow;
|
||||||
color: rgb(241 245 249);
|
color: rgb(241 245 249);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -698,27 +712,27 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
html[data-theme='dark'] .notice-info-dialog {
|
html[data-theme='dark'] .notice-info-dialog {
|
||||||
--el-bg-color: rgb(20, 20, 20);
|
--el-bg-color: @analysis-dark-bg;
|
||||||
--el-dialog-bg-color: rgb(20, 20, 20);
|
--el-dialog-bg-color: @analysis-dark-bg;
|
||||||
--el-fill-color-blank: rgb(20, 20, 20);
|
--el-fill-color-blank: @analysis-dark-bg;
|
||||||
|
|
||||||
.el-dialog {
|
.el-dialog {
|
||||||
background: rgb(20, 20, 20) !important;
|
background: @analysis-dark-bg !important;
|
||||||
--el-dialog-bg-color: rgb(20, 20, 20);
|
--el-dialog-bg-color: @analysis-dark-bg;
|
||||||
--el-bg-color: rgb(20, 20, 20);
|
--el-bg-color: @analysis-dark-bg;
|
||||||
--el-fill-color-blank: rgb(20, 20, 20);
|
--el-fill-color-blank: @analysis-dark-bg;
|
||||||
box-shadow: 0 14px 36px rgb(0 0 0 / 42%);
|
box-shadow: @analysis-dark-shadow;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-dialog__wrapper,
|
.el-dialog__wrapper,
|
||||||
.el-overlay-dialog,
|
.el-overlay-dialog,
|
||||||
.el-dialog__content {
|
.el-dialog__content {
|
||||||
background: rgb(20, 20, 20) !important;
|
background: @analysis-dark-bg !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-dialog__header {
|
.el-dialog__header {
|
||||||
border-bottom: 1px solid rgb(51 65 85) !important;
|
border-bottom: 1px solid rgb(51 65 85) !important;
|
||||||
background: rgb(20, 20, 20) !important;
|
background: @analysis-dark-bg !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-dialog__title {
|
.el-dialog__title {
|
||||||
@@ -730,14 +744,14 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.el-dialog__body {
|
.el-dialog__body {
|
||||||
background: rgb(20, 20, 20) !important;
|
background: @analysis-dark-bg !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-dialog__header,
|
.el-dialog__header,
|
||||||
.el-dialog__body,
|
.el-dialog__body,
|
||||||
.el-dialog__footer {
|
.el-dialog__footer {
|
||||||
--el-bg-color: rgb(20, 20, 20);
|
--el-bg-color: @analysis-dark-bg;
|
||||||
--el-fill-color-blank: rgb(20, 20, 20);
|
--el-fill-color-blank: @analysis-dark-bg;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-divider {
|
.el-divider {
|
||||||
@@ -746,7 +760,7 @@
|
|||||||
|
|
||||||
.notice-dialog {
|
.notice-dialog {
|
||||||
&__attachments-title {
|
&__attachments-title {
|
||||||
background: rgb(20, 20, 20);
|
background: @analysis-dark-bg;
|
||||||
color: rgb(226 232 240);
|
color: rgb(226 232 240);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -196,6 +196,10 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
|
@analysis-dark-bg: rgb(20, 20, 20);
|
||||||
|
@analysis-dark-hover-bg: rgb(30 41 59);
|
||||||
|
@analysis-dark-shadow: 0 10px 24px rgb(0 0 0 / 24%);
|
||||||
|
|
||||||
.oper-log-card {
|
.oper-log-card {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
@@ -369,7 +373,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
html[data-theme='dark'] .oper-log-card {
|
html[data-theme='dark'] .oper-log-card {
|
||||||
background: rgb(20, 20, 20);
|
background: @analysis-dark-bg;
|
||||||
|
|
||||||
.card-title {
|
.card-title {
|
||||||
color: rgb(203 213 225);
|
color: rgb(203 213 225);
|
||||||
@@ -378,8 +382,8 @@
|
|||||||
|
|
||||||
.query-panel,
|
.query-panel,
|
||||||
.table-panel {
|
.table-panel {
|
||||||
background: linear-gradient(180deg, rgb(20, 20, 20) 0%, rgb(28 28 28) 100%);
|
background: @analysis-dark-bg;
|
||||||
box-shadow: 0 10px 24px rgb(0 0 0 / 24%);
|
box-shadow: @analysis-dark-shadow;
|
||||||
}
|
}
|
||||||
|
|
||||||
.query-form {
|
.query-form {
|
||||||
@@ -391,7 +395,7 @@
|
|||||||
:deep(.el-select__wrapper) {
|
:deep(.el-select__wrapper) {
|
||||||
--el-fill-color-blank: rgb(20, 20, 20);
|
--el-fill-color-blank: rgb(20, 20, 20);
|
||||||
--el-bg-color: rgb(20, 20, 20);
|
--el-bg-color: rgb(20, 20, 20);
|
||||||
background: rgb(20, 20, 20);
|
background: @analysis-dark-bg;
|
||||||
box-shadow: 0 0 0 1px rgb(71 85 105) inset;
|
box-shadow: 0 0 0 1px rgb(71 85 105) inset;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -404,7 +408,7 @@
|
|||||||
:deep(.el-select-dropdown),
|
:deep(.el-select-dropdown),
|
||||||
:deep(.el-popper),
|
:deep(.el-popper),
|
||||||
:deep(.el-select__popper.el-popper) {
|
:deep(.el-select__popper.el-popper) {
|
||||||
background: rgb(20, 20, 20);
|
background: @analysis-dark-bg;
|
||||||
border-color: rgb(51 65 85);
|
border-color: rgb(51 65 85);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -415,7 +419,7 @@
|
|||||||
:deep(.el-select-dropdown__item.hover),
|
:deep(.el-select-dropdown__item.hover),
|
||||||
:deep(.el-select-dropdown__item:hover),
|
:deep(.el-select-dropdown__item:hover),
|
||||||
:deep(.el-select-dropdown__item.is-hovering) {
|
:deep(.el-select-dropdown__item.is-hovering) {
|
||||||
background: rgb(30 41 59);
|
background: @analysis-dark-hover-bg;
|
||||||
color: rgb(241 245 249);
|
color: rgb(241 245 249);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -453,28 +457,28 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
:deep(.el-button) {
|
:deep(.el-button) {
|
||||||
--el-fill-color-blank: rgb(30 41 59);
|
--el-fill-color-blank: @analysis-dark-bg;
|
||||||
--el-bg-color: rgb(30 41 59);
|
--el-bg-color: @analysis-dark-bg;
|
||||||
border-color: rgb(71 85 105);
|
border-color: rgb(71 85 105);
|
||||||
background: rgb(30 41 59);
|
background: @analysis-dark-bg;
|
||||||
color: rgb(226 232 240);
|
color: rgb(226 232 240);
|
||||||
}
|
}
|
||||||
|
|
||||||
:deep(.el-button:hover) {
|
:deep(.el-button:hover) {
|
||||||
border-color: rgb(96 165 250);
|
border-color: rgb(96 165 250);
|
||||||
background: rgb(37 99 235 / 22%);
|
background: @analysis-dark-hover-bg;
|
||||||
color: rgb(241 245 249);
|
color: rgb(241 245 249);
|
||||||
}
|
}
|
||||||
|
|
||||||
:deep(.el-button--primary) {
|
:deep(.el-button--primary) {
|
||||||
border-color: rgb(59 130 246);
|
border-color: rgb(96 165 250);
|
||||||
background: rgb(37 99 235);
|
background: @analysis-dark-bg;
|
||||||
color: rgb(248 250 252);
|
color: rgb(248 250 252);
|
||||||
}
|
}
|
||||||
|
|
||||||
:deep(.el-button--primary:hover) {
|
:deep(.el-button--primary:hover) {
|
||||||
border-color: rgb(96 165 250);
|
border-color: rgb(96 165 250);
|
||||||
background: rgb(59 130 246);
|
background: @analysis-dark-hover-bg;
|
||||||
color: rgb(248 250 252);
|
color: rgb(248 250 252);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -482,15 +486,15 @@
|
|||||||
.table-panel {
|
.table-panel {
|
||||||
.el-table {
|
.el-table {
|
||||||
--el-table-border-color: transparent;
|
--el-table-border-color: transparent;
|
||||||
--el-table-header-bg-color: rgb(20, 20, 20);
|
--el-table-header-bg-color: @analysis-dark-bg;
|
||||||
--el-table-tr-bg-color: transparent;
|
--el-table-tr-bg-color: transparent;
|
||||||
--el-table-row-hover-bg-color: rgb(30 41 59);
|
--el-table-row-hover-bg-color: @analysis-dark-hover-bg;
|
||||||
--el-table-text-color: rgb(148 163 184);
|
--el-table-text-color: rgb(148 163 184);
|
||||||
--el-table-header-text-color: rgb(226 232 240);
|
--el-table-header-text-color: rgb(226 232 240);
|
||||||
background: transparent;
|
background: transparent;
|
||||||
|
|
||||||
th.el-table__cell {
|
th.el-table__cell {
|
||||||
background: rgb(20, 20, 20);
|
background: @analysis-dark-bg;
|
||||||
}
|
}
|
||||||
|
|
||||||
th.el-table__cell,
|
th.el-table__cell,
|
||||||
@@ -499,11 +503,23 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.el-table__footer-wrapper td.el-table__cell {
|
.el-table__footer-wrapper td.el-table__cell {
|
||||||
background: rgb(20, 20, 20);
|
background: @analysis-dark-bg;
|
||||||
border-top: 1px solid rgb(51 65 85);
|
border-top: 1px solid rgb(51 65 85);
|
||||||
border-bottom: none;
|
border-bottom: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.el-loading-mask {
|
||||||
|
background-color: rgb(20 20 20 / 72%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-loading-spinner .path {
|
||||||
|
stroke: rgb(147 197 253);
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-loading-spinner .el-loading-text {
|
||||||
|
color: rgb(203 213 225);
|
||||||
|
}
|
||||||
|
|
||||||
.el-table__footer-wrapper .cell {
|
.el-table__footer-wrapper .cell {
|
||||||
color: rgb(226 232 240);
|
color: rgb(226 232 240);
|
||||||
}
|
}
|
||||||
@@ -517,7 +533,7 @@
|
|||||||
:deep(.el-pagination) {
|
:deep(.el-pagination) {
|
||||||
--el-pagination-text-color: rgb(226 232 240);
|
--el-pagination-text-color: rgb(226 232 240);
|
||||||
--el-pagination-button-color: rgb(226 232 240);
|
--el-pagination-button-color: rgb(226 232 240);
|
||||||
--el-pagination-button-bg-color: rgb(30 41 59);
|
--el-pagination-button-bg-color: @analysis-dark-bg;
|
||||||
--el-pagination-hover-color: rgb(147 197 253);
|
--el-pagination-hover-color: rgb(147 197 253);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -525,7 +541,7 @@
|
|||||||
:deep(.btn-next),
|
:deep(.btn-next),
|
||||||
:deep(.el-pager li),
|
:deep(.el-pager li),
|
||||||
:deep(.el-pagination button) {
|
:deep(.el-pagination button) {
|
||||||
background: rgb(30 41 59) !important;
|
background: @analysis-dark-bg !important;
|
||||||
color: rgb(226 232 240) !important;
|
color: rgb(226 232 240) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -578,7 +594,7 @@
|
|||||||
html[data-theme='dark'] .el-select-dropdown__item.hover,
|
html[data-theme='dark'] .el-select-dropdown__item.hover,
|
||||||
html[data-theme='dark'] .el-select-dropdown__item:hover,
|
html[data-theme='dark'] .el-select-dropdown__item:hover,
|
||||||
html[data-theme='dark'] .el-select-dropdown__item.is-hovering {
|
html[data-theme='dark'] .el-select-dropdown__item.is-hovering {
|
||||||
background: rgb(30 41 59) !important;
|
background: @analysis-dark-hover-bg !important;
|
||||||
color: rgb(241 245 249) !important;
|
color: rgb(241 245 249) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -590,7 +606,7 @@
|
|||||||
html[data-theme='dark'] .el-pagination .btn-next,
|
html[data-theme='dark'] .el-pagination .btn-next,
|
||||||
html[data-theme='dark'] .el-pagination .el-pager li,
|
html[data-theme='dark'] .el-pagination .el-pager li,
|
||||||
html[data-theme='dark'] .el-pagination button {
|
html[data-theme='dark'] .el-pagination button {
|
||||||
background: rgb(30 41 59) !important;
|
background: @analysis-dark-bg !important;
|
||||||
color: rgb(226 232 240) !important;
|
color: rgb(226 232 240) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -632,7 +648,7 @@
|
|||||||
|
|
||||||
html[data-theme='dark'] .oper-log-card .el-input.is-disabled .el-input__wrapper,
|
html[data-theme='dark'] .oper-log-card .el-input.is-disabled .el-input__wrapper,
|
||||||
html[data-theme='dark'] .oper-log-card .el-select.is-disabled .el-select__wrapper {
|
html[data-theme='dark'] .oper-log-card .el-select.is-disabled .el-select__wrapper {
|
||||||
background: rgb(30 41 59) !important;
|
background: @analysis-dark-bg !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
html[data-theme='dark'] .oper-log-card .el-input__suffix,
|
html[data-theme='dark'] .oper-log-card .el-input__suffix,
|
||||||
@@ -644,16 +660,16 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
html[data-theme='dark'] .oper-log-card .query-form__actions .el-button {
|
html[data-theme='dark'] .oper-log-card .query-form__actions .el-button {
|
||||||
--el-button-bg-color: rgb(30 41 59) !important;
|
--el-button-bg-color: @analysis-dark-bg !important;
|
||||||
--el-button-border-color: rgb(71 85 105) !important;
|
--el-button-border-color: rgb(71 85 105) !important;
|
||||||
--el-button-text-color: rgb(226 232 240) !important;
|
--el-button-text-color: rgb(226 232 240) !important;
|
||||||
--el-button-hover-bg-color: rgb(37 99 235 / 22%) !important;
|
--el-button-hover-bg-color: @analysis-dark-hover-bg !important;
|
||||||
--el-button-hover-border-color: rgb(96 165 250) !important;
|
--el-button-hover-border-color: rgb(96 165 250) !important;
|
||||||
--el-button-hover-text-color: rgb(241 245 249) !important;
|
--el-button-hover-text-color: rgb(241 245 249) !important;
|
||||||
--el-button-active-bg-color: rgb(37 99 235 / 28%) !important;
|
--el-button-active-bg-color: @analysis-dark-hover-bg !important;
|
||||||
--el-button-active-border-color: rgb(96 165 250) !important;
|
--el-button-active-border-color: rgb(96 165 250) !important;
|
||||||
--el-button-active-text-color: rgb(241 245 249) !important;
|
--el-button-active-text-color: rgb(241 245 249) !important;
|
||||||
background: rgb(30 41 59) !important;
|
background: @analysis-dark-bg !important;
|
||||||
border-color: rgb(71 85 105) !important;
|
border-color: rgb(71 85 105) !important;
|
||||||
color: rgb(226 232 240) !important;
|
color: rgb(226 232 240) !important;
|
||||||
box-shadow: none !important;
|
box-shadow: none !important;
|
||||||
@@ -661,26 +677,26 @@
|
|||||||
|
|
||||||
html[data-theme='dark'] .oper-log-card .query-form__actions .el-button:hover,
|
html[data-theme='dark'] .oper-log-card .query-form__actions .el-button:hover,
|
||||||
html[data-theme='dark'] .oper-log-card .query-form__actions .el-button:focus {
|
html[data-theme='dark'] .oper-log-card .query-form__actions .el-button:focus {
|
||||||
background: rgb(37 99 235 / 22%) !important;
|
background: @analysis-dark-hover-bg !important;
|
||||||
border-color: rgb(96 165 250) !important;
|
border-color: rgb(96 165 250) !important;
|
||||||
color: rgb(241 245 249) !important;
|
color: rgb(241 245 249) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
html[data-theme='dark'] .oper-log-card .query-form__actions .el-button--primary {
|
html[data-theme='dark'] .oper-log-card .query-form__actions .el-button--primary {
|
||||||
--el-button-bg-color: rgb(37 99 235) !important;
|
--el-button-bg-color: @analysis-dark-bg !important;
|
||||||
--el-button-border-color: rgb(59 130 246) !important;
|
--el-button-border-color: rgb(96 165 250) !important;
|
||||||
--el-button-text-color: rgb(248 250 252) !important;
|
--el-button-text-color: rgb(248 250 252) !important;
|
||||||
--el-button-hover-bg-color: rgb(59 130 246) !important;
|
--el-button-hover-bg-color: @analysis-dark-hover-bg !important;
|
||||||
--el-button-hover-border-color: rgb(96 165 250) !important;
|
--el-button-hover-border-color: rgb(96 165 250) !important;
|
||||||
--el-button-hover-text-color: rgb(248 250 252) !important;
|
--el-button-hover-text-color: rgb(248 250 252) !important;
|
||||||
background: rgb(37 99 235) !important;
|
background: @analysis-dark-bg !important;
|
||||||
border-color: rgb(59 130 246) !important;
|
border-color: rgb(96 165 250) !important;
|
||||||
color: rgb(248 250 252) !important;
|
color: rgb(248 250 252) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
html[data-theme='dark'] .oper-log-card .query-form__actions .el-button--primary:hover,
|
html[data-theme='dark'] .oper-log-card .query-form__actions .el-button--primary:hover,
|
||||||
html[data-theme='dark'] .oper-log-card .query-form__actions .el-button--primary:focus {
|
html[data-theme='dark'] .oper-log-card .query-form__actions .el-button--primary:focus {
|
||||||
background: rgb(59 130 246) !important;
|
background: @analysis-dark-hover-bg !important;
|
||||||
border-color: rgb(96 165 250) !important;
|
border-color: rgb(96 165 250) !important;
|
||||||
color: rgb(248 250 252) !important;
|
color: rgb(248 250 252) !important;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -184,6 +184,9 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
|
@analysis-dark-bg: rgb(20, 20, 20);
|
||||||
|
@analysis-dark-shadow: 0 10px 24px rgb(0 0 0 / 24%);
|
||||||
|
|
||||||
.province-card {
|
.province-card {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
@@ -241,7 +244,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
html[data-theme='dark'] .province-card {
|
html[data-theme='dark'] .province-card {
|
||||||
background: rgb(20, 20, 20);
|
background: @analysis-dark-bg;
|
||||||
|
|
||||||
.card-title {
|
.card-title {
|
||||||
color: rgb(203 213 225);
|
color: rgb(203 213 225);
|
||||||
@@ -253,8 +256,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.province-chart-panel {
|
.province-chart-panel {
|
||||||
background: linear-gradient(180deg, rgb(20, 20, 20) 0%, rgb(28 28 28) 100%);
|
background: @analysis-dark-bg;
|
||||||
box-shadow: 0 10px 24px rgb(0 0 0 / 24%);
|
box-shadow: @analysis-dark-shadow;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -157,6 +157,10 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
|
@analysis-dark-bg: rgb(20, 20, 20);
|
||||||
|
@analysis-dark-hover-bg: rgb(30 41 59);
|
||||||
|
@analysis-dark-shadow: 0 10px 24px rgb(0 0 0 / 24%);
|
||||||
|
|
||||||
.quick-login-card {
|
.quick-login-card {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
@@ -292,7 +296,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
html[data-theme='dark'] .quick-login-card {
|
html[data-theme='dark'] .quick-login-card {
|
||||||
background: rgb(20, 20, 20);
|
background: @analysis-dark-bg;
|
||||||
|
|
||||||
.card-title {
|
.card-title {
|
||||||
color: rgb(203 213 225);
|
color: rgb(203 213 225);
|
||||||
@@ -301,12 +305,13 @@
|
|||||||
|
|
||||||
.quick-login-item {
|
.quick-login-item {
|
||||||
border-color: rgb(51 65 85);
|
border-color: rgb(51 65 85);
|
||||||
background: rgb(20, 20, 20);
|
background: @analysis-dark-bg;
|
||||||
box-shadow: 0 10px 24px rgb(0 0 0 / 24%);
|
box-shadow: @analysis-dark-shadow;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
border-color: rgb(96 165 250);
|
border-color: rgb(96 165 250);
|
||||||
box-shadow: 0 14px 32px rgb(37 99 235 / 22%);
|
background: @analysis-dark-hover-bg;
|
||||||
|
box-shadow: @analysis-dark-shadow;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__name {
|
&__name {
|
||||||
@@ -314,7 +319,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
&__image-wrap {
|
&__image-wrap {
|
||||||
background: rgb(30 41 59);
|
background: @analysis-dark-bg;
|
||||||
border-color: rgb(59 130 246 / 35%);
|
border-color: rgb(59 130 246 / 35%);
|
||||||
box-shadow: 0 6px 14px rgb(37 99 235 / 16%);
|
box-shadow: 0 6px 14px rgb(37 99 235 / 16%);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -255,6 +255,10 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
|
@analysis-dark-bg: rgb(20, 20, 20);
|
||||||
|
@analysis-dark-hover-bg: rgb(30 41 59);
|
||||||
|
@analysis-dark-shadow: 0 10px 24px rgb(0 0 0 / 24%);
|
||||||
|
|
||||||
.notice-card {
|
.notice-card {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
@@ -568,7 +572,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
html[data-theme='dark'] .notice-card {
|
html[data-theme='dark'] .notice-card {
|
||||||
background: rgb(20, 20, 20);
|
background: @analysis-dark-bg;
|
||||||
|
|
||||||
.card-title {
|
.card-title {
|
||||||
color: rgb(203 213 225);
|
color: rgb(203 213 225);
|
||||||
@@ -593,15 +597,27 @@
|
|||||||
.table-container {
|
.table-container {
|
||||||
.el-table {
|
.el-table {
|
||||||
--el-table-border-color: transparent;
|
--el-table-border-color: transparent;
|
||||||
--el-table-header-bg-color: rgb(20, 20, 20);
|
--el-table-header-bg-color: @analysis-dark-bg;
|
||||||
--el-table-tr-bg-color: transparent;
|
--el-table-tr-bg-color: transparent;
|
||||||
--el-table-row-hover-bg-color: rgb(30 41 59);
|
--el-table-row-hover-bg-color: @analysis-dark-hover-bg;
|
||||||
--el-table-text-color: rgb(148 163 184);
|
--el-table-text-color: rgb(148 163 184);
|
||||||
--el-table-header-text-color: rgb(226 232 240);
|
--el-table-header-text-color: rgb(226 232 240);
|
||||||
background: transparent;
|
background: transparent;
|
||||||
|
|
||||||
th.el-table__cell {
|
th.el-table__cell {
|
||||||
background: rgb(20, 20, 20);
|
background: @analysis-dark-bg;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-loading-mask {
|
||||||
|
background-color: rgb(20 20 20 / 72%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-loading-spinner .path {
|
||||||
|
stroke: rgb(147 197 253);
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-loading-spinner .el-loading-text {
|
||||||
|
color: rgb(203 213 225);
|
||||||
}
|
}
|
||||||
|
|
||||||
th.el-table__cell,
|
th.el-table__cell,
|
||||||
@@ -629,7 +645,7 @@
|
|||||||
&__form-panel,
|
&__form-panel,
|
||||||
&__content,
|
&__content,
|
||||||
&__section-title {
|
&__section-title {
|
||||||
background: rgb(20, 20, 20);
|
background: @analysis-dark-bg;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__content {
|
&__content {
|
||||||
@@ -649,7 +665,7 @@
|
|||||||
&__textarea :deep(.el-textarea__inner) {
|
&__textarea :deep(.el-textarea__inner) {
|
||||||
border: 1px solid rgb(71 85 105) !important;
|
border: 1px solid rgb(71 85 105) !important;
|
||||||
border-color: rgb(71 85 105);
|
border-color: rgb(71 85 105);
|
||||||
background: rgb(20, 20, 20);
|
background: @analysis-dark-bg;
|
||||||
color: rgb(226 232 240);
|
color: rgb(226 232 240);
|
||||||
box-shadow: none !important;
|
box-shadow: none !important;
|
||||||
}
|
}
|
||||||
@@ -668,38 +684,38 @@
|
|||||||
|
|
||||||
&__textarea :deep(.el-input__count) {
|
&__textarea :deep(.el-input__count) {
|
||||||
color: rgb(148 163 184);
|
color: rgb(148 163 184);
|
||||||
background: rgb(20, 20, 20);
|
background: @analysis-dark-bg;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
html[data-theme='dark'] .todo-info-dialog {
|
html[data-theme='dark'] .todo-info-dialog {
|
||||||
--el-bg-color: rgb(20, 20, 20);
|
--el-bg-color: @analysis-dark-bg;
|
||||||
--el-dialog-bg-color: rgb(20, 20, 20);
|
--el-dialog-bg-color: @analysis-dark-bg;
|
||||||
--el-fill-color-blank: rgb(20, 20, 20);
|
--el-fill-color-blank: @analysis-dark-bg;
|
||||||
|
|
||||||
.el-dialog {
|
.el-dialog {
|
||||||
background: rgb(20, 20, 20) !important;
|
background: @analysis-dark-bg !important;
|
||||||
--el-dialog-bg-color: rgb(20, 20, 20);
|
--el-dialog-bg-color: @analysis-dark-bg;
|
||||||
--el-bg-color: rgb(20, 20, 20);
|
--el-bg-color: @analysis-dark-bg;
|
||||||
--el-fill-color-blank: rgb(20, 20, 20);
|
--el-fill-color-blank: @analysis-dark-bg;
|
||||||
box-shadow: 0 14px 36px rgb(0 0 0 / 42%);
|
box-shadow: @analysis-dark-shadow;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-dialog__wrapper,
|
.el-dialog__wrapper,
|
||||||
.el-overlay-dialog,
|
.el-overlay-dialog,
|
||||||
.el-dialog__content {
|
.el-dialog__content {
|
||||||
background: rgb(20, 20, 20) !important;
|
background: @analysis-dark-bg !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-dialog__header {
|
.el-dialog__header {
|
||||||
border-bottom: 1px solid rgb(51 65 85) !important;
|
border-bottom: 1px solid rgb(51 65 85) !important;
|
||||||
background: rgb(20, 20, 20) !important;
|
background: @analysis-dark-bg !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-dialog__body,
|
.el-dialog__body,
|
||||||
.el-dialog__footer {
|
.el-dialog__footer {
|
||||||
background: rgb(20, 20, 20) !important;
|
background: @analysis-dark-bg !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-textarea,
|
.el-textarea,
|
||||||
@@ -708,8 +724,8 @@
|
|||||||
--el-input-border-color: rgb(71 85 105);
|
--el-input-border-color: rgb(71 85 105);
|
||||||
--el-input-hover-border-color: rgb(96 165 250);
|
--el-input-hover-border-color: rgb(96 165 250);
|
||||||
--el-input-focus-border-color: rgb(96 165 250);
|
--el-input-focus-border-color: rgb(96 165 250);
|
||||||
--el-fill-color-blank: rgb(20, 20, 20);
|
--el-fill-color-blank: @analysis-dark-bg;
|
||||||
background: rgb(20, 20, 20) !important;
|
background: @analysis-dark-bg !important;
|
||||||
box-shadow: none !important;
|
box-shadow: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -728,8 +744,8 @@
|
|||||||
.el-dialog__header,
|
.el-dialog__header,
|
||||||
.el-dialog__body,
|
.el-dialog__body,
|
||||||
.el-dialog__footer {
|
.el-dialog__footer {
|
||||||
--el-bg-color: rgb(20, 20, 20);
|
--el-bg-color: @analysis-dark-bg;
|
||||||
--el-fill-color-blank: rgb(20, 20, 20);
|
--el-fill-color-blank: @analysis-dark-bg;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-divider {
|
.el-divider {
|
||||||
@@ -742,26 +758,26 @@
|
|||||||
|
|
||||||
.todo-dialog__footer {
|
.todo-dialog__footer {
|
||||||
.el-button:not(.el-button--primary) {
|
.el-button:not(.el-button--primary) {
|
||||||
border-color: rgb(71 85 105);
|
border-color: rgb(96 165 250);
|
||||||
background: rgb(30 41 59);
|
background: @analysis-dark-bg;
|
||||||
color: rgb(226 232 240);
|
color: rgb(226 232 240);
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-button:not(.el-button--primary):hover {
|
.el-button:not(.el-button--primary):hover {
|
||||||
border-color: rgb(96 165 250);
|
border-color: rgb(96 165 250);
|
||||||
background: rgb(37 99 235 / 22%);
|
background: @analysis-dark-hover-bg;
|
||||||
color: rgb(241 245 249);
|
color: rgb(241 245 249);
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-button--primary {
|
.el-button--primary {
|
||||||
border-color: rgb(59 130 246);
|
border-color: rgb(96 165 250);
|
||||||
background: rgb(37 99 235);
|
background: @analysis-dark-bg;
|
||||||
color: rgb(248 250 252);
|
color: rgb(248 250 252);
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-button--primary:hover {
|
.el-button--primary:hover {
|
||||||
border-color: rgb(96 165 250);
|
border-color: rgb(96 165 250);
|
||||||
background: rgb(59 130 246);
|
background: @analysis-dark-hover-bg;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,6 +43,12 @@
|
|||||||
</script>
|
</script>
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
@dark-bg: #141414;
|
@dark-bg: #141414;
|
||||||
|
@desktop-page-gap: 12px;
|
||||||
|
@desktop-page-padding: 0;
|
||||||
|
@desktop-card-radius: 10px;
|
||||||
|
@desktop-card-border: 1px solid rgb(226 232 240);
|
||||||
|
@desktop-card-shadow: 0 1px 3px rgb(15 23 42 / 0.06);
|
||||||
|
@desktop-dark-border: rgb(51 65 85);
|
||||||
|
|
||||||
.analysis-page-wrapper {
|
.analysis-page-wrapper {
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -97,18 +103,19 @@
|
|||||||
--analysis-card-title-padding: 8px 16px;
|
--analysis-card-title-padding: 8px 16px;
|
||||||
--analysis-card-content-padding: 8px 12px 12px;
|
--analysis-card-content-padding: 8px 12px 12px;
|
||||||
--analysis-card-item-gap: 8px;
|
--analysis-card-item-gap: 8px;
|
||||||
--analysis-card-radius: 10px;
|
--analysis-gap: @desktop-page-gap;
|
||||||
|
--analysis-card-radius: @desktop-card-radius;
|
||||||
display: flex;
|
display: flex;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
max-height: 100%;
|
max-height: 100%;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
gap: var(--analysis-gap);
|
gap: var(--analysis-gap);
|
||||||
padding: 0;
|
padding: @desktop-page-padding;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
border-radius: 10px;
|
border-radius: @desktop-card-radius;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mySpring-analysis .analysis-left,
|
.mySpring-analysis .analysis-left,
|
||||||
@@ -148,16 +155,16 @@
|
|||||||
min-width: 0;
|
min-width: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
border-radius: var(--analysis-card-radius);
|
border-radius: var(--analysis-card-radius);
|
||||||
border: 1px solid rgb(226 232 240);
|
border: @desktop-card-border;
|
||||||
background: rgb(255, 255, 255);
|
background: rgb(255, 255, 255);
|
||||||
box-shadow: 0 1px 3px rgb(15 23 42 / 0.06);
|
box-shadow: @desktop-card-shadow;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
color: rgb(71 85 105);
|
color: rgb(71 85 105);
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
html[data-theme='dark'] .mySpring-analysis .analysis-panel {
|
html[data-theme='dark'] .mySpring-analysis .analysis-panel {
|
||||||
border-color: rgb(51 65 85);
|
border-color: @desktop-dark-border;
|
||||||
background: @dark-bg !important;
|
background: @dark-bg !important;
|
||||||
color: rgb(203 213 225);
|
color: rgb(203 213 225);
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
@@ -171,7 +178,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
html[data-theme='dark'] .mySpring-analysis {
|
html[data-theme='dark'] .mySpring-analysis {
|
||||||
border-radius: 10px;
|
border-radius: @desktop-card-radius;
|
||||||
}
|
}
|
||||||
|
|
||||||
html[data-theme='dark'] .mySpring-analysis,
|
html[data-theme='dark'] .mySpring-analysis,
|
||||||
|
|||||||
@@ -0,0 +1,585 @@
|
|||||||
|
<template>
|
||||||
|
<div ref="contractCardRef" class="contract-info-card">
|
||||||
|
<div class="card-title">
|
||||||
|
<span>项目合同</span>
|
||||||
|
<el-button class="card-title__more" link type="primary" @click="goMore">更多</el-button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card-content">
|
||||||
|
<div class="contract-overview">
|
||||||
|
<div class="task-chart-panel task-chart-panel--pie">
|
||||||
|
<div ref="pieChartRef" class="task-chart"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="task-chart-panel task-chart-panel--bar">
|
||||||
|
<div ref="barChartRef" class="task-chart"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { computed, nextTick, onMounted, onUnmounted, ref } from 'vue';
|
||||||
|
import { useRouter } from 'vue-router';
|
||||||
|
import * as echarts from 'echarts';
|
||||||
|
import { MyProjectContract, myProjectContractListAll } from '@jeesite/biz/api/biz/myProjectContract';
|
||||||
|
import { DictData, dictDataListData } from '@jeesite/core/api/sys/dictData';
|
||||||
|
import { useUserStore } from '@jeesite/core/store/modules/user';
|
||||||
|
import { firstCurrentYear, formatToDate } from '@jeesite/core/utils/dateUtil';
|
||||||
|
|
||||||
|
const router = useRouter();
|
||||||
|
const userStore = useUserStore();
|
||||||
|
const userinfo = computed(() => userStore.getUserInfo);
|
||||||
|
|
||||||
|
const contractCardRef = ref<HTMLElement>();
|
||||||
|
const pieChartRef = ref<HTMLElement>();
|
||||||
|
const barChartRef = ref<HTMLElement>();
|
||||||
|
const sourceData = ref<MyProjectContract[]>([]);
|
||||||
|
const statusDict = ref<DictData[]>([]);
|
||||||
|
|
||||||
|
const STATUS_COLORS = ['#3B82F6', '#10B981', '#F97316', '#EC4899', '#8B5CF6', '#06B6D4'];
|
||||||
|
let pieChartInstance: echarts.ECharts | null = null;
|
||||||
|
let barChartInstance: echarts.ECharts | null = null;
|
||||||
|
let resizeObserver: ResizeObserver | null = null;
|
||||||
|
let themeObserver: MutationObserver | null = null;
|
||||||
|
|
||||||
|
function goMore() {
|
||||||
|
router.push('/biz/myProjectContract/list');
|
||||||
|
}
|
||||||
|
|
||||||
|
const pieChartData = computed(() => {
|
||||||
|
if (!statusDict.value.length) {
|
||||||
|
const fallbackMap = new Map<string, number>();
|
||||||
|
sourceData.value.forEach((item) => {
|
||||||
|
const label = item.contractStatus || '未设置';
|
||||||
|
fallbackMap.set(label, (fallbackMap.get(label) || 0) + 1);
|
||||||
|
});
|
||||||
|
return Array.from(fallbackMap.entries()).map(([name, value], index) => ({
|
||||||
|
name,
|
||||||
|
value,
|
||||||
|
itemStyle: { color: STATUS_COLORS[index % STATUS_COLORS.length] },
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
const countMap = new Map<string, number>();
|
||||||
|
sourceData.value.forEach((item) => {
|
||||||
|
const key = item.contractStatus || 'unknown';
|
||||||
|
countMap.set(key, (countMap.get(key) || 0) + 1);
|
||||||
|
});
|
||||||
|
|
||||||
|
return statusDict.value
|
||||||
|
.map((item, index) => ({
|
||||||
|
name: item.dictLabelRaw,
|
||||||
|
value: countMap.get(item.dictValue || '') || 0,
|
||||||
|
itemStyle: { color: STATUS_COLORS[index % STATUS_COLORS.length] },
|
||||||
|
}))
|
||||||
|
.filter((item) => item.value > 0);
|
||||||
|
});
|
||||||
|
|
||||||
|
const barChartData = computed(() => {
|
||||||
|
const statusItems = statusDict.value.length
|
||||||
|
? statusDict.value.map((item, index) => ({
|
||||||
|
key: item.dictValue,
|
||||||
|
label: item.dictLabelRaw,
|
||||||
|
color: STATUS_COLORS[index % STATUS_COLORS.length],
|
||||||
|
}))
|
||||||
|
: [];
|
||||||
|
|
||||||
|
const monthStatusMap = new Map<string, Map<string, number>>();
|
||||||
|
const monthOrderMap = new Map<string, number>();
|
||||||
|
|
||||||
|
sourceData.value.forEach((item) => {
|
||||||
|
if (!item.signDate) return;
|
||||||
|
const date = new Date(item.signDate);
|
||||||
|
if (Number.isNaN(date.getTime())) return;
|
||||||
|
const monthLabel = `${date.getMonth() + 1}月`;
|
||||||
|
monthOrderMap.set(monthLabel, date.getMonth() + 1);
|
||||||
|
const statusKey = item.contractStatus || 'unknown';
|
||||||
|
if (!monthStatusMap.has(monthLabel)) {
|
||||||
|
monthStatusMap.set(monthLabel, new Map<string, number>());
|
||||||
|
}
|
||||||
|
const monthMap = monthStatusMap.get(monthLabel)!;
|
||||||
|
monthMap.set(statusKey, (monthMap.get(statusKey) || 0) + 1);
|
||||||
|
});
|
||||||
|
|
||||||
|
const months = Array.from(monthStatusMap.keys()).sort((a, b) => {
|
||||||
|
return (monthOrderMap.get(a) || 0) - (monthOrderMap.get(b) || 0);
|
||||||
|
});
|
||||||
|
|
||||||
|
const totalByMonth = months.map((month) => {
|
||||||
|
const monthMap = monthStatusMap.get(month);
|
||||||
|
return Array.from(monthMap?.values() || []).reduce((sum, count) => sum + count, 0);
|
||||||
|
});
|
||||||
|
|
||||||
|
const fallbackStatusMap = new Map<string, number>();
|
||||||
|
sourceData.value.forEach((item) => {
|
||||||
|
if (!statusDict.value.length) {
|
||||||
|
const key = item.contractStatus || '未设置';
|
||||||
|
fallbackStatusMap.set(key, (fallbackStatusMap.get(key) || 0) + 1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const fallbackSeries = Array.from(fallbackStatusMap.keys()).map((key, index) => ({
|
||||||
|
key,
|
||||||
|
label: key,
|
||||||
|
color: STATUS_COLORS[index % STATUS_COLORS.length],
|
||||||
|
}));
|
||||||
|
|
||||||
|
return {
|
||||||
|
months,
|
||||||
|
totals: totalByMonth,
|
||||||
|
statusItems: statusItems.length ? statusItems : fallbackSeries,
|
||||||
|
monthStatusMap,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
async function getDict() {
|
||||||
|
try {
|
||||||
|
statusDict.value = await dictDataListData({ dictType: 'contract_status' });
|
||||||
|
} catch (error) {
|
||||||
|
statusDict.value = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getList() {
|
||||||
|
try {
|
||||||
|
const reqParams = {
|
||||||
|
createTime_gte: firstCurrentYear(),
|
||||||
|
createUser: userinfo.value.loginCode,
|
||||||
|
};
|
||||||
|
const res = await myProjectContractListAll(reqParams);
|
||||||
|
sourceData.value = res || [];
|
||||||
|
} catch (error) {
|
||||||
|
sourceData.value = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderPieChart() {
|
||||||
|
if (!pieChartRef.value) return;
|
||||||
|
if (!pieChartInstance) {
|
||||||
|
pieChartInstance = echarts.init(pieChartRef.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
const isDark = document.documentElement.getAttribute('data-theme') === 'dark';
|
||||||
|
const total = pieChartData.value.reduce((sum, item) => sum + Number(item.value || 0), 0);
|
||||||
|
const data = total
|
||||||
|
? pieChartData.value
|
||||||
|
: statusDict.value.map((item, index) => ({
|
||||||
|
name: item.dictLabelRaw,
|
||||||
|
value: 0,
|
||||||
|
itemStyle: { color: STATUS_COLORS[index % STATUS_COLORS.length] },
|
||||||
|
}));
|
||||||
|
const legendData = statusDict.value.length
|
||||||
|
? statusDict.value.map((item) => item.dictLabelRaw)
|
||||||
|
: pieChartData.value.map((item) => item.name);
|
||||||
|
const series: echarts.SeriesOption[] = [];
|
||||||
|
|
||||||
|
if (!total) {
|
||||||
|
series.push({
|
||||||
|
name: '空态环',
|
||||||
|
type: 'pie',
|
||||||
|
radius: ['46%', '72%'],
|
||||||
|
center: ['50%', '44%'],
|
||||||
|
silent: true,
|
||||||
|
legendHoverLink: false,
|
||||||
|
tooltip: {
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
label: {
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
labelLine: {
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
itemStyle: {
|
||||||
|
color: isDark ? 'rgba(148, 163, 184, 0.18)' : 'rgba(203, 213, 225, 0.55)',
|
||||||
|
borderRadius: 10,
|
||||||
|
borderColor: isDark ? '#141414' : '#ffffff',
|
||||||
|
borderWidth: 3,
|
||||||
|
},
|
||||||
|
data: [{ name: 'empty-ring', value: 1 }],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
series.push({
|
||||||
|
name: '合同状态',
|
||||||
|
type: 'pie',
|
||||||
|
radius: total ? ['46%', '72%'] : [0, 0],
|
||||||
|
center: ['50%', '44%'],
|
||||||
|
avoidLabelOverlap: true,
|
||||||
|
minAngle: total ? 4 : 0,
|
||||||
|
itemStyle: {
|
||||||
|
borderRadius: 10,
|
||||||
|
borderColor: isDark ? '#141414' : '#ffffff',
|
||||||
|
borderWidth: 3,
|
||||||
|
},
|
||||||
|
label: {
|
||||||
|
show: total,
|
||||||
|
formatter: ({ name, value, percent }) => (total ? `${name}\n${value}项 / ${percent}%` : ''),
|
||||||
|
color: isDark ? '#e2e8f0' : '#334155',
|
||||||
|
fontSize: 12,
|
||||||
|
},
|
||||||
|
emphasis: {
|
||||||
|
scale: true,
|
||||||
|
scaleSize: 6,
|
||||||
|
},
|
||||||
|
data,
|
||||||
|
silent: !total,
|
||||||
|
labelLine: {
|
||||||
|
show: total,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
pieChartInstance.setOption({
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'item',
|
||||||
|
backgroundColor: isDark ? 'rgba(20, 20, 20, 0.96)' : 'rgba(255, 255, 255, 0.96)',
|
||||||
|
borderColor: isDark ? 'rgb(51 65 85)' : 'rgb(226 232 240)',
|
||||||
|
borderWidth: 1,
|
||||||
|
textStyle: {
|
||||||
|
color: isDark ? '#e2e8f0' : '#334155',
|
||||||
|
},
|
||||||
|
formatter: ({ name, value, percent }) => {
|
||||||
|
if (!total) return `${name}<br/>数量:0`;
|
||||||
|
return `${name}<br/>数量:${value}<br/>占比:${percent}%`;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
show: legendData.length > 0,
|
||||||
|
bottom: 4,
|
||||||
|
left: 'center',
|
||||||
|
itemWidth: 10,
|
||||||
|
itemHeight: 10,
|
||||||
|
data: legendData,
|
||||||
|
textStyle: {
|
||||||
|
color: isDark ? '#cbd5e1' : '#475569',
|
||||||
|
fontSize: 12,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
series,
|
||||||
|
graphic: total
|
||||||
|
? [
|
||||||
|
{
|
||||||
|
type: 'text',
|
||||||
|
left: 'center',
|
||||||
|
top: '34%',
|
||||||
|
style: {
|
||||||
|
text: '合同总数',
|
||||||
|
fill: isDark ? '#94a3b8' : '#64748b',
|
||||||
|
fontSize: 12,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'text',
|
||||||
|
left: 'center',
|
||||||
|
top: '41%',
|
||||||
|
style: {
|
||||||
|
text: `${total}`,
|
||||||
|
fill: isDark ? '#f8fafc' : '#0f172a',
|
||||||
|
fontSize: 24,
|
||||||
|
fontWeight: 700,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
: [],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderBarChart() {
|
||||||
|
if (!barChartRef.value) return;
|
||||||
|
if (!barChartInstance) {
|
||||||
|
barChartInstance = echarts.init(barChartRef.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
const isDark = document.documentElement.getAttribute('data-theme') === 'dark';
|
||||||
|
const { months, totals, statusItems, monthStatusMap } = barChartData.value;
|
||||||
|
const hasData = totals.some((item) => item > 0);
|
||||||
|
const categories = months.length ? months : [];
|
||||||
|
const series = statusItems.length
|
||||||
|
? statusItems.map((status) => ({
|
||||||
|
name: status.label,
|
||||||
|
type: 'bar',
|
||||||
|
stack: 'month-total',
|
||||||
|
barWidth: '12%',
|
||||||
|
itemStyle: {
|
||||||
|
color: status.color,
|
||||||
|
borderRadius: 0,
|
||||||
|
},
|
||||||
|
emphasis: {
|
||||||
|
focus: 'series',
|
||||||
|
},
|
||||||
|
label: {
|
||||||
|
show: true,
|
||||||
|
position: 'inside',
|
||||||
|
formatter: ({ value }) => (Number(value) > 0 ? `${value}` : ''),
|
||||||
|
color: '#ffffff',
|
||||||
|
fontSize: 11,
|
||||||
|
},
|
||||||
|
data: categories.map((month) => monthStatusMap.get(month)?.get(status.key) || 0),
|
||||||
|
}))
|
||||||
|
: [
|
||||||
|
{
|
||||||
|
type: 'bar',
|
||||||
|
barWidth: '12%',
|
||||||
|
itemStyle: {
|
||||||
|
color: isDark ? '#334155' : '#E2E8F0',
|
||||||
|
borderRadius: [10, 10, 0, 0],
|
||||||
|
},
|
||||||
|
data: categories.map(() => 0),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
if (hasData) {
|
||||||
|
series.push({
|
||||||
|
name: '总数',
|
||||||
|
type: 'bar',
|
||||||
|
stack: 'month-total',
|
||||||
|
silent: true,
|
||||||
|
legendHoverLink: false,
|
||||||
|
itemStyle: {
|
||||||
|
color: 'rgba(0,0,0,0)',
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
label: {
|
||||||
|
show: true,
|
||||||
|
position: 'top',
|
||||||
|
color: isDark ? '#cbd5e1' : '#475569',
|
||||||
|
fontSize: 11,
|
||||||
|
formatter: ({ dataIndex }) => (totals[dataIndex] > 0 ? `${totals[dataIndex]}` : ''),
|
||||||
|
},
|
||||||
|
data: categories.map(() => 0),
|
||||||
|
z: 10,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
barChartInstance.setOption({
|
||||||
|
grid: {
|
||||||
|
left: 12,
|
||||||
|
right: 12,
|
||||||
|
top: 52,
|
||||||
|
bottom: 10,
|
||||||
|
containLabel: true,
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'axis',
|
||||||
|
axisPointer: {
|
||||||
|
type: 'shadow',
|
||||||
|
},
|
||||||
|
backgroundColor: isDark ? 'rgba(20, 20, 20, 0.96)' : 'rgba(255, 255, 255, 0.96)',
|
||||||
|
borderColor: isDark ? 'rgb(51 65 85)' : 'rgb(226 232 240)',
|
||||||
|
borderWidth: 1,
|
||||||
|
textStyle: {
|
||||||
|
color: isDark ? '#e2e8f0' : '#334155',
|
||||||
|
},
|
||||||
|
formatter: (params) => {
|
||||||
|
const dataIndex = params[0]?.dataIndex || 0;
|
||||||
|
if (!hasData) return '';
|
||||||
|
const lines = params
|
||||||
|
.filter((item) => item.seriesName !== '总数' && Number(item.value) > 0)
|
||||||
|
.map((item) => `${item.marker}${item.seriesName}:${item.value}项`);
|
||||||
|
lines.push(`总数:${totals[dataIndex]}项`);
|
||||||
|
return `${categories[dataIndex]}<br/>${lines.join('<br/>')}`;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
top: 6,
|
||||||
|
left: 'center',
|
||||||
|
itemGap: 16,
|
||||||
|
data: statusItems.map((item) => item.label),
|
||||||
|
textStyle: {
|
||||||
|
color: isDark ? '#e2e8f0' : '#475569',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
xAxis: {
|
||||||
|
type: 'category',
|
||||||
|
data: categories,
|
||||||
|
boundaryGap: ['2%', '2%'],
|
||||||
|
axisTick: {
|
||||||
|
alignWithLabel: true,
|
||||||
|
},
|
||||||
|
axisLine: {
|
||||||
|
lineStyle: {
|
||||||
|
color: isDark ? '#475569' : '#cbd5e1',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
axisLabel: {
|
||||||
|
color: isDark ? '#cbd5e1' : '#64748b',
|
||||||
|
interval: 0,
|
||||||
|
margin: 8,
|
||||||
|
rotate: 30,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
type: 'value',
|
||||||
|
minInterval: 1,
|
||||||
|
name: '数量',
|
||||||
|
nameTextStyle: {
|
||||||
|
color: isDark ? '#94a3b8' : '#64748b',
|
||||||
|
padding: [0, 0, 2, 0],
|
||||||
|
},
|
||||||
|
splitLine: {
|
||||||
|
lineStyle: {
|
||||||
|
color: isDark ? 'rgba(71, 85, 105, 0.35)' : 'rgba(203, 213, 225, 0.55)',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
axisLabel: {
|
||||||
|
color: isDark ? '#94a3b8' : '#64748b',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
series,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderCharts() {
|
||||||
|
renderPieChart();
|
||||||
|
renderBarChart();
|
||||||
|
}
|
||||||
|
|
||||||
|
function resizeCharts() {
|
||||||
|
pieChartInstance?.resize();
|
||||||
|
barChartInstance?.resize();
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
await Promise.all([getDict(), getList()]);
|
||||||
|
await nextTick();
|
||||||
|
renderCharts();
|
||||||
|
|
||||||
|
if (contractCardRef.value) {
|
||||||
|
resizeObserver = new ResizeObserver(() => {
|
||||||
|
resizeCharts();
|
||||||
|
});
|
||||||
|
resizeObserver.observe(contractCardRef.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addEventListener('resize', resizeCharts);
|
||||||
|
|
||||||
|
themeObserver = new MutationObserver(() => {
|
||||||
|
nextTick(() => {
|
||||||
|
renderCharts();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
themeObserver.observe(document.documentElement, {
|
||||||
|
attributes: true,
|
||||||
|
attributeFilter: ['data-theme'],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
resizeObserver?.disconnect();
|
||||||
|
themeObserver?.disconnect();
|
||||||
|
window.removeEventListener('resize', resizeCharts);
|
||||||
|
pieChartInstance?.dispose();
|
||||||
|
barChartInstance?.dispose();
|
||||||
|
pieChartInstance = null;
|
||||||
|
barChartInstance = null;
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less">
|
||||||
|
@workbench-dark-panel-bg: rgb(20, 20, 20);
|
||||||
|
@workbench-dark-shadow: 0 10px 24px rgb(0 0 0 / 24%);
|
||||||
|
|
||||||
|
.contract-info-card {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
box-sizing: border-box;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
.card-title {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 8px 16px;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
|
line-height: 20px;
|
||||||
|
color: rgb(51 65 85);
|
||||||
|
border-bottom: 1px solid rgb(226 232 240);
|
||||||
|
background: transparent;
|
||||||
|
|
||||||
|
&__more {
|
||||||
|
padding: 0;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-content {
|
||||||
|
flex: 1;
|
||||||
|
min-height: 0;
|
||||||
|
padding: 16px;
|
||||||
|
overflow: hidden;
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contract-overview {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: minmax(220px, 0.9fr) minmax(0, 1.6fr);
|
||||||
|
gap: 12px;
|
||||||
|
height: 100%;
|
||||||
|
min-height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.task-chart-panel {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
min-width: 0;
|
||||||
|
min-height: 0;
|
||||||
|
padding: 12px;
|
||||||
|
border-radius: 12px;
|
||||||
|
background: rgb(255, 255, 255);
|
||||||
|
box-shadow: 0 8px 24px rgb(148 163 184 / 14%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.task-chart {
|
||||||
|
flex: 1;
|
||||||
|
min-height: 0;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
html[data-theme='dark'] .contract-info-card {
|
||||||
|
.card-title {
|
||||||
|
color: rgb(203 213 225);
|
||||||
|
border-bottom-color: rgb(51 65 85);
|
||||||
|
|
||||||
|
&__more:deep(.el-button) {
|
||||||
|
color: rgb(147 197 253);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.task-chart-panel {
|
||||||
|
background: @workbench-dark-panel-bg;
|
||||||
|
box-shadow: @workbench-dark-shadow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 1100px) {
|
||||||
|
.contract-info-card {
|
||||||
|
.contract-overview {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.contract-info-card {
|
||||||
|
.card-content {
|
||||||
|
padding: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.task-chart-panel {
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.task-chart {
|
||||||
|
min-height: 220px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -331,6 +331,10 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
|
@workbench-dark-panel-bg: rgb(20, 20, 20);
|
||||||
|
@workbench-dark-solid-bg: rgb(20, 20, 20);
|
||||||
|
@workbench-dark-shadow: 0 10px 24px rgb(0 0 0 / 24%);
|
||||||
|
|
||||||
.note-card {
|
.note-card {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
@@ -508,14 +512,14 @@
|
|||||||
|
|
||||||
.metric-item,
|
.metric-item,
|
||||||
.note-chart-panel {
|
.note-chart-panel {
|
||||||
background: linear-gradient(180deg, rgb(20, 20, 20) 0%, rgb(28 28 28) 100%);
|
background: @workbench-dark-panel-bg;
|
||||||
box-shadow: 0 10px 24px rgb(0 0 0 / 24%);
|
box-shadow: @workbench-dark-shadow;
|
||||||
}
|
}
|
||||||
|
|
||||||
.metric-item {
|
.metric-item {
|
||||||
&__pane {
|
&__pane {
|
||||||
background: linear-gradient(180deg, rgb(20, 20, 20) 0%, rgb(28 28 28) 100%);
|
background: @workbench-dark-panel-bg;
|
||||||
box-shadow: 0 10px 24px rgb(0 0 0 / 24%);
|
box-shadow: @workbench-dark-shadow;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__extra,
|
&__extra,
|
||||||
@@ -525,12 +529,12 @@
|
|||||||
|
|
||||||
&__label {
|
&__label {
|
||||||
border-color: rgb(51 65 85);
|
border-color: rgb(51 65 85);
|
||||||
background: rgb(20, 20, 20);
|
background: @workbench-dark-solid-bg;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__label--active {
|
&__label--active {
|
||||||
border-color: rgb(59 130 246 / 40%);
|
border-color: rgb(59 130 246 / 40%);
|
||||||
background: rgb(37 99 235 / 14%) !important;
|
background: @workbench-dark-solid-bg !important;
|
||||||
color: rgb(191 219 254) !important;
|
color: rgb(191 219 254) !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,612 @@
|
|||||||
|
<template>
|
||||||
|
<div ref="projectTaskCardRef" class="project-task-card">
|
||||||
|
<div class="card-title">
|
||||||
|
<span>项目任务</span>
|
||||||
|
<el-button class="card-title__more" link type="primary" @click="goMore">更多</el-button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card-content">
|
||||||
|
<div class="project-task-overview">
|
||||||
|
<div class="task-chart-panel task-chart-panel--pie">
|
||||||
|
<div ref="pieChartRef" class="task-chart"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="task-chart-panel task-chart-panel--bar">
|
||||||
|
<div ref="barChartRef" class="task-chart"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { computed, nextTick, onMounted, onUnmounted, ref } from 'vue';
|
||||||
|
import { useRouter } from 'vue-router';
|
||||||
|
import * as echarts from 'echarts';
|
||||||
|
import { MyProjectTask, myProjectTaskListAll } from '@jeesite/biz/api/biz/myProjectTask';
|
||||||
|
import { DictData, dictDataListData } from '@jeesite/core/api/sys/dictData';
|
||||||
|
import { useUserStore } from '@jeesite/core/store/modules/user';
|
||||||
|
import { firstCurrentYear, formatToDate } from '@jeesite/core/utils/dateUtil';
|
||||||
|
|
||||||
|
const router = useRouter();
|
||||||
|
const userStore = useUserStore();
|
||||||
|
const userinfo = computed(() => userStore.getUserInfo);
|
||||||
|
|
||||||
|
const projectTaskCardRef = ref<HTMLElement>();
|
||||||
|
const pieChartRef = ref<HTMLElement>();
|
||||||
|
const barChartRef = ref<HTMLElement>();
|
||||||
|
const sourceData = ref<MyProjectTask[]>([]);
|
||||||
|
const statusDict = ref<DictData[]>([]);
|
||||||
|
|
||||||
|
const STATUS_COLORS = ['#3B82F6', '#10B981', '#F97316', '#EC4899', '#8B5CF6', '#06B6D4'];
|
||||||
|
let pieChartInstance: echarts.ECharts | null = null;
|
||||||
|
let barChartInstance: echarts.ECharts | null = null;
|
||||||
|
let resizeObserver: ResizeObserver | null = null;
|
||||||
|
let themeObserver: MutationObserver | null = null;
|
||||||
|
|
||||||
|
function goMore() {
|
||||||
|
router.push('/biz/myProjectTask/list');
|
||||||
|
}
|
||||||
|
|
||||||
|
const pieChartData = computed(() => {
|
||||||
|
if (!statusDict.value.length) {
|
||||||
|
const fallbackMap = new Map<string, number>();
|
||||||
|
sourceData.value.forEach((item) => {
|
||||||
|
const label = item.taskStatus || '未设置';
|
||||||
|
fallbackMap.set(label, (fallbackMap.get(label) || 0) + 1);
|
||||||
|
});
|
||||||
|
return Array.from(fallbackMap.entries()).map(([name, value], index) => ({
|
||||||
|
name,
|
||||||
|
value,
|
||||||
|
itemStyle: { color: STATUS_COLORS[index % STATUS_COLORS.length] },
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
const countMap = new Map<string, number>();
|
||||||
|
sourceData.value.forEach((item) => {
|
||||||
|
const key = item.taskStatus || 'unknown';
|
||||||
|
countMap.set(key, (countMap.get(key) || 0) + 1);
|
||||||
|
});
|
||||||
|
|
||||||
|
return statusDict.value
|
||||||
|
.map((item, index) => ({
|
||||||
|
name: item.dictLabelRaw,
|
||||||
|
value: countMap.get(item.dictValue || '') || 0,
|
||||||
|
itemStyle: { color: STATUS_COLORS[index % STATUS_COLORS.length] },
|
||||||
|
}))
|
||||||
|
.filter((item) => item.value > 0);
|
||||||
|
});
|
||||||
|
|
||||||
|
const barChartData = computed(() => {
|
||||||
|
const statusItems = statusDict.value.length
|
||||||
|
? statusDict.value.map((item, index) => ({
|
||||||
|
key: item.dictValue,
|
||||||
|
label: item.dictLabelRaw,
|
||||||
|
color: STATUS_COLORS[index % STATUS_COLORS.length],
|
||||||
|
}))
|
||||||
|
: [];
|
||||||
|
|
||||||
|
const monthStatusMap = new Map<string, Map<string, number>>();
|
||||||
|
const monthOrderMap = new Map<string, number>();
|
||||||
|
|
||||||
|
sourceData.value.forEach((item) => {
|
||||||
|
if (!item.createTime) return;
|
||||||
|
const date = new Date(item.createTime);
|
||||||
|
if (Number.isNaN(date.getTime())) return;
|
||||||
|
const monthLabel = `${date.getMonth() + 1}月`;
|
||||||
|
monthOrderMap.set(monthLabel, date.getMonth() + 1);
|
||||||
|
const statusKey = item.taskStatus || 'unknown';
|
||||||
|
if (!monthStatusMap.has(monthLabel)) {
|
||||||
|
monthStatusMap.set(monthLabel, new Map<string, number>());
|
||||||
|
}
|
||||||
|
const monthMap = monthStatusMap.get(monthLabel)!;
|
||||||
|
monthMap.set(statusKey, (monthMap.get(statusKey) || 0) + 1);
|
||||||
|
});
|
||||||
|
|
||||||
|
const months = Array.from(monthStatusMap.keys()).sort((a, b) => {
|
||||||
|
return (monthOrderMap.get(a) || 0) - (monthOrderMap.get(b) || 0);
|
||||||
|
});
|
||||||
|
|
||||||
|
const totalByMonth = months.map((month) => {
|
||||||
|
const monthMap = monthStatusMap.get(month);
|
||||||
|
return Array.from(monthMap?.values() || []).reduce((sum, count) => sum + count, 0);
|
||||||
|
});
|
||||||
|
|
||||||
|
const fallbackStatusMap = new Map<string, number>();
|
||||||
|
sourceData.value.forEach((item) => {
|
||||||
|
if (!statusDict.value.length) {
|
||||||
|
const key = item.taskStatus || '未设置';
|
||||||
|
fallbackStatusMap.set(key, (fallbackStatusMap.get(key) || 0) + 1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const fallbackSeries = Array.from(fallbackStatusMap.keys()).map((key, index) => ({
|
||||||
|
key,
|
||||||
|
label: key,
|
||||||
|
color: STATUS_COLORS[index % STATUS_COLORS.length],
|
||||||
|
}));
|
||||||
|
|
||||||
|
return {
|
||||||
|
months,
|
||||||
|
totals: totalByMonth,
|
||||||
|
statusItems: statusItems.length ? statusItems : fallbackSeries,
|
||||||
|
monthStatusMap,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
async function getDict() {
|
||||||
|
try {
|
||||||
|
statusDict.value = await dictDataListData({ dictType: 'task_status' });
|
||||||
|
} catch (error) {
|
||||||
|
statusDict.value = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getList() {
|
||||||
|
try {
|
||||||
|
const reqParams = {
|
||||||
|
createTime_gte: firstCurrentYear(),
|
||||||
|
createUser: userinfo.value.loginCode,
|
||||||
|
};
|
||||||
|
const res = await myProjectTaskListAll(reqParams);
|
||||||
|
sourceData.value = res || [];
|
||||||
|
} catch (error) {
|
||||||
|
sourceData.value = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderPieChart() {
|
||||||
|
if (!pieChartRef.value) return;
|
||||||
|
if (!pieChartInstance) {
|
||||||
|
pieChartInstance = echarts.init(pieChartRef.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
const isDark = document.documentElement.getAttribute('data-theme') === 'dark';
|
||||||
|
const total = pieChartData.value.reduce((sum, item) => sum + Number(item.value || 0), 0);
|
||||||
|
const data = total
|
||||||
|
? pieChartData.value
|
||||||
|
: statusDict.value.map((item, index) => ({
|
||||||
|
name: item.dictLabelRaw,
|
||||||
|
value: 0,
|
||||||
|
itemStyle: { color: STATUS_COLORS[index % STATUS_COLORS.length] },
|
||||||
|
}));
|
||||||
|
const legendData = statusDict.value.length
|
||||||
|
? statusDict.value.map((item) => item.dictLabelRaw)
|
||||||
|
: pieChartData.value.map((item) => item.name);
|
||||||
|
const series: echarts.SeriesOption[] = [];
|
||||||
|
|
||||||
|
if (!total) {
|
||||||
|
series.push({
|
||||||
|
name: '空态环',
|
||||||
|
type: 'pie',
|
||||||
|
radius: ['46%', '72%'],
|
||||||
|
center: ['50%', '44%'],
|
||||||
|
silent: true,
|
||||||
|
legendHoverLink: false,
|
||||||
|
tooltip: {
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
label: {
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
labelLine: {
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
itemStyle: {
|
||||||
|
color: isDark ? 'rgba(148, 163, 184, 0.18)' : 'rgba(203, 213, 225, 0.55)',
|
||||||
|
borderRadius: 10,
|
||||||
|
borderColor: isDark ? '#141414' : '#ffffff',
|
||||||
|
borderWidth: 3,
|
||||||
|
},
|
||||||
|
data: [{ name: 'empty-ring', value: 1 }],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
series.push({
|
||||||
|
name: '任务状态',
|
||||||
|
type: 'pie',
|
||||||
|
radius: total ? ['46%', '72%'] : [0, 0],
|
||||||
|
center: ['50%', '44%'],
|
||||||
|
avoidLabelOverlap: true,
|
||||||
|
minAngle: total ? 4 : 0,
|
||||||
|
itemStyle: {
|
||||||
|
borderRadius: 10,
|
||||||
|
borderColor: isDark ? '#141414' : '#ffffff',
|
||||||
|
borderWidth: 3,
|
||||||
|
},
|
||||||
|
label: {
|
||||||
|
show: total,
|
||||||
|
formatter: ({ name, value, percent }) => (total ? `${name}\n${value}项 / ${percent}%` : ''),
|
||||||
|
color: isDark ? '#e2e8f0' : '#334155',
|
||||||
|
fontSize: 12,
|
||||||
|
},
|
||||||
|
emphasis: {
|
||||||
|
scale: true,
|
||||||
|
scaleSize: 6,
|
||||||
|
},
|
||||||
|
data,
|
||||||
|
silent: !total,
|
||||||
|
labelLine: {
|
||||||
|
show: total,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
pieChartInstance.setOption({
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'item',
|
||||||
|
backgroundColor: isDark ? 'rgba(20, 20, 20, 0.96)' : 'rgba(255, 255, 255, 0.96)',
|
||||||
|
borderColor: isDark ? 'rgb(51 65 85)' : 'rgb(226 232 240)',
|
||||||
|
borderWidth: 1,
|
||||||
|
textStyle: {
|
||||||
|
color: isDark ? '#e2e8f0' : '#334155',
|
||||||
|
},
|
||||||
|
formatter: ({ name, value, percent }) => {
|
||||||
|
if (!total) return `${name}<br/>数量:0`;
|
||||||
|
return `${name}<br/>数量:${value}<br/>占比:${percent}%`;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
show: legendData.length > 0,
|
||||||
|
bottom: 4,
|
||||||
|
left: 'center',
|
||||||
|
itemWidth: 10,
|
||||||
|
itemHeight: 10,
|
||||||
|
data: legendData,
|
||||||
|
textStyle: {
|
||||||
|
color: isDark ? '#cbd5e1' : '#475569',
|
||||||
|
fontSize: 12,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
series,
|
||||||
|
graphic: total
|
||||||
|
? [
|
||||||
|
{
|
||||||
|
type: 'text',
|
||||||
|
left: 'center',
|
||||||
|
top: '34%',
|
||||||
|
style: {
|
||||||
|
text: '任务总数',
|
||||||
|
fill: isDark ? '#94a3b8' : '#64748b',
|
||||||
|
fontSize: 12,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'text',
|
||||||
|
left: 'center',
|
||||||
|
top: '41%',
|
||||||
|
style: {
|
||||||
|
text: `${total}`,
|
||||||
|
fill: isDark ? '#f8fafc' : '#0f172a',
|
||||||
|
fontSize: 24,
|
||||||
|
fontWeight: 700,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
: [],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderBarChart() {
|
||||||
|
if (!barChartRef.value) return;
|
||||||
|
if (!barChartInstance) {
|
||||||
|
barChartInstance = echarts.init(barChartRef.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
const isDark = document.documentElement.getAttribute('data-theme') === 'dark';
|
||||||
|
const { months, totals, statusItems, monthStatusMap } = barChartData.value;
|
||||||
|
const hasData = totals.some((item) => item > 0);
|
||||||
|
const categories = months.length ? months : [];
|
||||||
|
const series = statusItems.length
|
||||||
|
? statusItems.map((status) => ({
|
||||||
|
name: status.label,
|
||||||
|
type: 'bar',
|
||||||
|
stack: 'month-total',
|
||||||
|
barWidth: '12%',
|
||||||
|
itemStyle: {
|
||||||
|
color: status.color,
|
||||||
|
borderRadius: 0,
|
||||||
|
},
|
||||||
|
emphasis: {
|
||||||
|
focus: 'series',
|
||||||
|
},
|
||||||
|
label: {
|
||||||
|
show: true,
|
||||||
|
position: 'inside',
|
||||||
|
formatter: ({ value }) => (Number(value) > 0 ? `${value}` : ''),
|
||||||
|
color: '#ffffff',
|
||||||
|
fontSize: 11,
|
||||||
|
},
|
||||||
|
data: categories.map((month) => monthStatusMap.get(month)?.get(status.key) || 0),
|
||||||
|
}))
|
||||||
|
: [
|
||||||
|
{
|
||||||
|
type: 'bar',
|
||||||
|
barWidth: '12%',
|
||||||
|
itemStyle: {
|
||||||
|
color: isDark ? '#334155' : '#E2E8F0',
|
||||||
|
borderRadius: [10, 10, 0, 0],
|
||||||
|
},
|
||||||
|
data: categories.map(() => 0),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
if (hasData) {
|
||||||
|
series.push({
|
||||||
|
name: '总数',
|
||||||
|
type: 'bar',
|
||||||
|
stack: 'month-total',
|
||||||
|
silent: true,
|
||||||
|
legendHoverLink: false,
|
||||||
|
itemStyle: {
|
||||||
|
color: 'rgba(0,0,0,0)',
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
label: {
|
||||||
|
show: true,
|
||||||
|
position: 'top',
|
||||||
|
color: isDark ? '#cbd5e1' : '#475569',
|
||||||
|
fontSize: 11,
|
||||||
|
formatter: ({ dataIndex }) => (totals[dataIndex] > 0 ? `${totals[dataIndex]}` : ''),
|
||||||
|
},
|
||||||
|
data: categories.map(() => 0),
|
||||||
|
z: 10,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
barChartInstance.setOption({
|
||||||
|
grid: {
|
||||||
|
left: 12,
|
||||||
|
right: 12,
|
||||||
|
top: 52,
|
||||||
|
bottom: 10,
|
||||||
|
containLabel: true,
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'axis',
|
||||||
|
axisPointer: {
|
||||||
|
type: 'shadow',
|
||||||
|
},
|
||||||
|
backgroundColor: isDark ? 'rgba(20, 20, 20, 0.96)' : 'rgba(255, 255, 255, 0.96)',
|
||||||
|
borderColor: isDark ? 'rgb(51 65 85)' : 'rgb(226 232 240)',
|
||||||
|
borderWidth: 1,
|
||||||
|
textStyle: {
|
||||||
|
color: isDark ? '#e2e8f0' : '#334155',
|
||||||
|
},
|
||||||
|
formatter: (params) => {
|
||||||
|
const dataIndex = params[0]?.dataIndex || 0;
|
||||||
|
if (!hasData) return '';
|
||||||
|
const lines = params
|
||||||
|
.filter((item) => item.seriesName !== '总数' && Number(item.value) > 0)
|
||||||
|
.map((item) => `${item.marker}${item.seriesName}:${item.value}项`);
|
||||||
|
lines.push(`总数:${totals[dataIndex]}项`);
|
||||||
|
return `${categories[dataIndex]}<br/>${lines.join('<br/>')}`;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
top: 6,
|
||||||
|
left: 'center',
|
||||||
|
itemGap: 16,
|
||||||
|
data: statusItems.map((item) => item.label),
|
||||||
|
textStyle: {
|
||||||
|
color: isDark ? '#e2e8f0' : '#475569',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
xAxis: {
|
||||||
|
type: 'category',
|
||||||
|
data: categories,
|
||||||
|
boundaryGap: ['2%', '2%'],
|
||||||
|
axisTick: {
|
||||||
|
alignWithLabel: true,
|
||||||
|
},
|
||||||
|
axisLine: {
|
||||||
|
lineStyle: {
|
||||||
|
color: isDark ? '#475569' : '#cbd5e1',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
axisLabel: {
|
||||||
|
color: isDark ? '#cbd5e1' : '#64748b',
|
||||||
|
interval: 0,
|
||||||
|
margin: 8,
|
||||||
|
rotate: 30,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
type: 'value',
|
||||||
|
name: '数量',
|
||||||
|
nameTextStyle: {
|
||||||
|
color: isDark ? '#94a3b8' : '#64748b',
|
||||||
|
padding: [0, 0, 2, 0],
|
||||||
|
},
|
||||||
|
splitLine: {
|
||||||
|
lineStyle: {
|
||||||
|
color: isDark ? 'rgba(71, 85, 105, 0.35)' : 'rgba(203, 213, 225, 0.55)',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
axisLabel: {
|
||||||
|
color: isDark ? '#94a3b8' : '#64748b',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
series,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderCharts() {
|
||||||
|
renderPieChart();
|
||||||
|
renderBarChart();
|
||||||
|
}
|
||||||
|
|
||||||
|
function resizeCharts() {
|
||||||
|
pieChartInstance?.resize();
|
||||||
|
barChartInstance?.resize();
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
await Promise.all([getDict(), getList()]);
|
||||||
|
await nextTick();
|
||||||
|
renderCharts();
|
||||||
|
|
||||||
|
if (projectTaskCardRef.value) {
|
||||||
|
resizeObserver = new ResizeObserver(() => {
|
||||||
|
resizeCharts();
|
||||||
|
});
|
||||||
|
resizeObserver.observe(projectTaskCardRef.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addEventListener('resize', resizeCharts);
|
||||||
|
|
||||||
|
themeObserver = new MutationObserver(() => {
|
||||||
|
nextTick(() => {
|
||||||
|
renderCharts();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
themeObserver.observe(document.documentElement, {
|
||||||
|
attributes: true,
|
||||||
|
attributeFilter: ['data-theme'],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
resizeObserver?.disconnect();
|
||||||
|
themeObserver?.disconnect();
|
||||||
|
window.removeEventListener('resize', resizeCharts);
|
||||||
|
pieChartInstance?.dispose();
|
||||||
|
barChartInstance?.dispose();
|
||||||
|
pieChartInstance = null;
|
||||||
|
barChartInstance = null;
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less">
|
||||||
|
@workbench-dark-panel-bg: rgb(20, 20, 20);
|
||||||
|
@workbench-dark-shadow: 0 10px 24px rgb(0 0 0 / 24%);
|
||||||
|
|
||||||
|
.project-task-card {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
box-sizing: border-box;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
.card-title {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 8px 16px;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
|
line-height: 20px;
|
||||||
|
color: rgb(51 65 85);
|
||||||
|
border-bottom: 1px solid rgb(226 232 240);
|
||||||
|
background: transparent;
|
||||||
|
|
||||||
|
&__more {
|
||||||
|
padding: 0;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-content {
|
||||||
|
flex: 1;
|
||||||
|
min-height: 0;
|
||||||
|
padding: 16px;
|
||||||
|
overflow: hidden;
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.project-task-overview {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: minmax(220px, 0.9fr) minmax(0, 1.6fr);
|
||||||
|
gap: 12px;
|
||||||
|
height: 100%;
|
||||||
|
min-height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.task-chart-panel {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
min-width: 0;
|
||||||
|
min-height: 0;
|
||||||
|
padding: 12px;
|
||||||
|
border-radius: 12px;
|
||||||
|
background: rgb(255, 255, 255);
|
||||||
|
box-shadow: 0 8px 24px rgb(148 163 184 / 14%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.panel-header {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 2px;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.panel-title {
|
||||||
|
color: rgb(51 65 85);
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 600;
|
||||||
|
line-height: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.panel-subtitle {
|
||||||
|
color: rgb(100 116 139);
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.task-chart {
|
||||||
|
flex: 1;
|
||||||
|
min-height: 0;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
html[data-theme='dark'] .project-task-card {
|
||||||
|
.card-title {
|
||||||
|
color: rgb(203 213 225);
|
||||||
|
border-bottom-color: rgb(51 65 85);
|
||||||
|
|
||||||
|
&__more:deep(.el-button) {
|
||||||
|
color: rgb(147 197 253);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.task-chart-panel {
|
||||||
|
background: @workbench-dark-panel-bg;
|
||||||
|
box-shadow: @workbench-dark-shadow;
|
||||||
|
}
|
||||||
|
|
||||||
|
.panel-title {
|
||||||
|
color: rgb(226 232 240);
|
||||||
|
}
|
||||||
|
|
||||||
|
.panel-subtitle {
|
||||||
|
color: rgb(148 163 184);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 1100px) {
|
||||||
|
.project-task-card {
|
||||||
|
.project-task-overview {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.project-task-card {
|
||||||
|
.card-content {
|
||||||
|
padding: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.task-chart-panel {
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.task-chart {
|
||||||
|
min-height: 220px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -314,6 +314,10 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
|
@workbench-dark-panel-bg: rgb(20, 20, 20);
|
||||||
|
@workbench-dark-solid-bg: rgb(20, 20, 20);
|
||||||
|
@workbench-dark-shadow: 0 10px 24px rgb(0 0 0 / 24%);
|
||||||
|
|
||||||
.schedule-card {
|
.schedule-card {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
@@ -700,14 +704,14 @@
|
|||||||
|
|
||||||
.summary-item,
|
.summary-item,
|
||||||
.schedule-panel {
|
.schedule-panel {
|
||||||
background: linear-gradient(180deg, rgb(20, 20, 20) 0%, rgb(28 28 28) 100%);
|
background: @workbench-dark-panel-bg;
|
||||||
box-shadow: 0 10px 24px rgb(0 0 0 / 24%);
|
box-shadow: @workbench-dark-shadow;
|
||||||
}
|
}
|
||||||
|
|
||||||
.summary-item {
|
.summary-item {
|
||||||
&__pane {
|
&__pane {
|
||||||
background: linear-gradient(180deg, rgb(20, 20, 20) 0%, rgb(28 28 28) 100%);
|
background: @workbench-dark-panel-bg;
|
||||||
box-shadow: 0 10px 24px rgb(0 0 0 / 24%);
|
box-shadow: @workbench-dark-shadow;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__extra,
|
&__extra,
|
||||||
@@ -717,7 +721,7 @@
|
|||||||
|
|
||||||
&__label {
|
&__label {
|
||||||
border-color: rgb(51 65 85);
|
border-color: rgb(51 65 85);
|
||||||
background: rgb(20, 20, 20);
|
background: @workbench-dark-solid-bg;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -734,12 +738,12 @@
|
|||||||
|
|
||||||
.panel-tag,
|
.panel-tag,
|
||||||
.timeline-scroll {
|
.timeline-scroll {
|
||||||
background: linear-gradient(180deg, rgb(20, 20, 20) 0%, rgb(28 28 28) 100%);
|
background: @workbench-dark-panel-bg;
|
||||||
box-shadow: 0 10px 24px rgb(0 0 0 / 24%);
|
box-shadow: @workbench-dark-shadow;
|
||||||
}
|
}
|
||||||
|
|
||||||
.timeline-row__hint {
|
.timeline-row__hint {
|
||||||
background: rgb(30 41 59 / 75%);
|
background: @workbench-dark-solid-bg;
|
||||||
}
|
}
|
||||||
|
|
||||||
.timeline-row__hint-title {
|
.timeline-row__hint-title {
|
||||||
@@ -756,7 +760,7 @@
|
|||||||
|
|
||||||
.timeline-event {
|
.timeline-event {
|
||||||
border-color: rgb(51 65 85);
|
border-color: rgb(51 65 85);
|
||||||
background: rgb(30 41 59 / 55%);
|
background: @workbench-dark-solid-bg;
|
||||||
color: rgb(226 232 240);
|
color: rgb(226 232 240);
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
@@ -778,7 +782,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
&__label {
|
&__label {
|
||||||
background: rgb(69 10 10);
|
background: @workbench-dark-solid-bg;
|
||||||
color: rgb(254 202 202);
|
color: rgb(254 202 202);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<PageWrapper :contentFullHeight="true">
|
<PageWrapper :contentFullHeight="true" :dense="true" title="false" contentClass="workbench-page-wrapper">
|
||||||
<template #headerContent>
|
<template #headerContent>
|
||||||
<WorkbenchHeader />
|
<WorkbenchHeader />
|
||||||
</template>
|
</template>
|
||||||
@@ -10,12 +10,16 @@
|
|||||||
<NoteInfo />
|
<NoteInfo />
|
||||||
</div>
|
</div>
|
||||||
<div class="workbench-col">
|
<div class="workbench-col">
|
||||||
<ScheduleInfo />
|
<ScheduleInfo />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="workbench-row">
|
<div class="workbench-row">
|
||||||
<div class="workbench-col">下左</div>
|
<div class="workbench-col">
|
||||||
<div class="workbench-col">下右</div>
|
<ProjectTask />
|
||||||
|
</div>
|
||||||
|
<div class="workbench-col">
|
||||||
|
<ContractInfo />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -26,6 +30,8 @@
|
|||||||
import { PageWrapper } from '@jeesite/core/components/Page';
|
import { PageWrapper } from '@jeesite/core/components/Page';
|
||||||
import WorkbenchHeader from './components/WorkbenchHeader.vue';
|
import WorkbenchHeader from './components/WorkbenchHeader.vue';
|
||||||
import NoteInfo from './components/NoteInfo.vue';
|
import NoteInfo from './components/NoteInfo.vue';
|
||||||
|
import ProjectTask from './components/ProjectTask.vue';
|
||||||
|
import ContractInfo from './components/ContractInfo.vue';
|
||||||
import ScheduleInfo from './components/ScheduleInfo.vue';
|
import ScheduleInfo from './components/ScheduleInfo.vue';
|
||||||
|
|
||||||
const loading = ref(true);
|
const loading = ref(true);
|
||||||
@@ -36,44 +42,64 @@
|
|||||||
|
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
@dark-bg: #141414;
|
@dark-bg: #141414;
|
||||||
|
@desktop-page-gap: 12px;
|
||||||
|
@desktop-page-padding: 0;
|
||||||
|
@desktop-card-radius: 10px;
|
||||||
|
@desktop-card-border: 1px solid rgb(226 232 240);
|
||||||
|
@desktop-card-shadow: 0 1px 3px rgb(15 23 42 / 0.06);
|
||||||
|
@desktop-dark-border: rgb(51 65 85);
|
||||||
|
|
||||||
|
.workbench-page-wrapper {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
height: 100%;
|
||||||
|
min-height: 0;
|
||||||
|
padding: 0 !important;
|
||||||
|
overflow: hidden !important;
|
||||||
|
background: transparent !important;
|
||||||
|
}
|
||||||
|
|
||||||
.jeesite-workbench {
|
.jeesite-workbench {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
flex: 1;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
background: rgb(255, 255, 255);
|
background: rgb(255, 255, 255);
|
||||||
border-radius: 10px;
|
border-radius: @desktop-card-radius;
|
||||||
}
|
}
|
||||||
|
|
||||||
.jeesite-workbench .workbench-layout {
|
.jeesite-workbench .workbench-layout {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
flex: 1;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 8px;
|
gap: @desktop-page-gap;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
padding: 0;
|
padding: @desktop-page-padding;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
border-radius: 10px;
|
border-radius: @desktop-card-radius;
|
||||||
}
|
}
|
||||||
|
|
||||||
.jeesite-workbench .workbench-row {
|
.jeesite-workbench .workbench-row {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex: 1 1 0;
|
flex: 1 1 0;
|
||||||
gap: 8px;
|
gap: @desktop-page-gap;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.jeesite-workbench .workbench-col {
|
.jeesite-workbench .workbench-col {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
border-radius: 10px;
|
border-radius: @desktop-card-radius;
|
||||||
border: 1px solid rgb(226 232 240);
|
border: @desktop-card-border;
|
||||||
background: rgb(255, 255, 255);
|
background: rgb(255, 255, 255);
|
||||||
box-shadow: 0 1px 3px rgb(15 23 42 / 0.06);
|
box-shadow: @desktop-card-shadow;
|
||||||
color: rgb(71 85 105);
|
color: rgb(71 85 105);
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
@@ -91,7 +117,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
html[data-theme='dark'] .jeesite-workbench .workbench-col {
|
html[data-theme='dark'] .jeesite-workbench .workbench-col {
|
||||||
border-color: rgb(51 65 85);
|
border-color: @desktop-dark-border;
|
||||||
background: @dark-bg !important;
|
background: @dark-bg !important;
|
||||||
color: rgb(226 232 240);
|
color: rgb(226 232 240);
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
|
|||||||
@@ -19,4 +19,12 @@ export function formatToDate(date: dayjs.ConfigType | undefined = undefined, for
|
|||||||
return dayjs(date).format(format);
|
return dayjs(date).format(format);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function firstCurrentYear(format = DATE_FORMAT): string {
|
||||||
|
return dayjs().startOf('year').format(format);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function firstCurrentMonth(format = DATE_FORMAT): string {
|
||||||
|
return dayjs().startOf('month').format(format);
|
||||||
|
}
|
||||||
|
|
||||||
export const dateUtil = dayjs;
|
export const dateUtil = dayjs;
|
||||||
|
|||||||
Reference in New Issue
Block a user