进度填报大屏界面基本功能
This commit is contained in:
@ -1,6 +1,6 @@
|
|||||||
import request from '@/utils/request';
|
import request from '@/utils/request';
|
||||||
import { AxiosPromise } from 'axios';
|
import { AxiosPromise } from 'axios';
|
||||||
import { ProgressCategoryVO, ProgressCategoryForm, ProgressCategoryQuery, ProgressPlanForm, lastTimeVo, workScheduleListVO, workScheduleListQuery, progressPlanDetailForm } from '@/api/progress/plan/types';
|
import { ProgressCategoryVO, ProgressCategoryForm, ProgressCategoryQuery, ProgressPlanForm, lastTimeVo, workScheduleListVO, workScheduleListQuery, progressPlanDetailForm, pvModuleListQuery, pvModuleListVO } from '@/api/progress/plan/types';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询进度类别列表
|
* 查询进度类别列表
|
||||||
@ -99,7 +99,7 @@ export const workScheduleAddPlan = (data: ProgressPlanForm) => {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取进度计划详细信息
|
* 获取进度计划详细信息
|
||||||
* @param data
|
* @param params
|
||||||
*/
|
*/
|
||||||
export const workScheduleList = (query: workScheduleListQuery):AxiosPromise<workScheduleListVO[]> => {
|
export const workScheduleList = (query: workScheduleListQuery):AxiosPromise<workScheduleListVO[]> => {
|
||||||
return request({
|
return request({
|
||||||
@ -109,6 +109,17 @@ export const workScheduleList = (query: workScheduleListQuery):AxiosPromise<work
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取进度类别坐标信息
|
||||||
|
* @param params
|
||||||
|
*/
|
||||||
|
export const workScheduleListPosition = (id: string):AxiosPromise<any> => {
|
||||||
|
return request({
|
||||||
|
url: '/progress/progressCategory/coordinate/' + id,
|
||||||
|
method: 'get',
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 新增进度计划详情(百分比设施)
|
* 新增进度计划详情(百分比设施)
|
||||||
* @param data
|
* @param data
|
||||||
@ -120,9 +131,53 @@ export const workScheduleSubmit = (data: progressPlanDetailForm) => {
|
|||||||
data: data
|
data: data
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
export const workScheduleDel=()=>{}
|
|
||||||
|
|
||||||
export const pvModuleList=()=>{}
|
/**
|
||||||
export const addDaily=()=>{}
|
* 获取进度计划详情未完成设施详细信息
|
||||||
export const getDailyBook=()=>{}
|
* @param params
|
||||||
export const deleteDaily=()=>{}
|
*/
|
||||||
|
export const pvModuleList = (query: pvModuleListQuery):AxiosPromise<pvModuleListVO[]> => {
|
||||||
|
return request({
|
||||||
|
url: '/progress/progressPlanDetail/detail/unFinish/' + query.id ,
|
||||||
|
method: 'get',
|
||||||
|
params:query
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增进度计划详情(普通设施)
|
||||||
|
* @param data
|
||||||
|
*/
|
||||||
|
export const addDaily = (data: progressPlanDetailForm) => {
|
||||||
|
return request({
|
||||||
|
url: '/progress/progressPlanDetail/insert/detail',
|
||||||
|
method: 'post',
|
||||||
|
data: data
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取进度计划详情已完成设施详细信息
|
||||||
|
* @param params
|
||||||
|
*/
|
||||||
|
export const getDailyBook = (query: pvModuleListQuery):AxiosPromise<pvModuleListVO[]> => {
|
||||||
|
return request({
|
||||||
|
url: '/progress/progressPlanDetail/detail/finished/'+ query.id,
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除进度计划详情
|
||||||
|
* @param id
|
||||||
|
*/
|
||||||
|
export const deleteDaily = (query: {id:string,detailIdList:string[]}) => {
|
||||||
|
return request({
|
||||||
|
url: '/progress/progressPlanDetail/remove/detail',
|
||||||
|
method: 'delete',
|
||||||
|
params: query
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const workScheduleDel=()=>{}
|
@ -28,6 +28,8 @@ export interface ProgressCategoryVO {
|
|||||||
* 子对象
|
* 子对象
|
||||||
*/
|
*/
|
||||||
children: ProgressCategoryVO[];
|
children: ProgressCategoryVO[];
|
||||||
|
threeChildren: any[];
|
||||||
|
hasChildren:any;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ProgressCategoryForm extends BaseEntity {
|
export interface ProgressCategoryForm extends BaseEntity {
|
||||||
@ -88,9 +90,22 @@ export interface workScheduleListVO {
|
|||||||
}[];
|
}[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface pvModuleListQuery {
|
||||||
|
id: string | number;
|
||||||
|
pageSize?: number;
|
||||||
|
pageNum?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface pvModuleListVO {
|
||||||
|
id: string | number;
|
||||||
|
name: string;
|
||||||
|
status: string;
|
||||||
|
}
|
||||||
|
|
||||||
export interface progressPlanDetailForm {
|
export interface progressPlanDetailForm {
|
||||||
id: string | number;
|
id: string | number;
|
||||||
finishedNumber: number;
|
finishedNumber?: number;
|
||||||
|
finishedDetailIdList?: any[];
|
||||||
submitTime?: string;
|
submitTime?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
63
src/api/progress/progressCategoryTemplate/index.ts
Normal file
63
src/api/progress/progressCategoryTemplate/index.ts
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
import request from '@/utils/request';
|
||||||
|
import { AxiosPromise } from 'axios';
|
||||||
|
import { ProgressCategoryTemplateVO, ProgressCategoryTemplateForm, ProgressCategoryTemplateQuery } from '@/api/progress/progressCategoryTemplate/types';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询进度类别模版列表
|
||||||
|
* @param query
|
||||||
|
* @returns {*}
|
||||||
|
*/
|
||||||
|
|
||||||
|
export const listProgressCategoryTemplate = (query?: ProgressCategoryTemplateQuery): AxiosPromise<ProgressCategoryTemplateVO[]> => {
|
||||||
|
return request({
|
||||||
|
url: '/progress/progressCategoryTemplate/list',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询进度类别模版详细
|
||||||
|
* @param id
|
||||||
|
*/
|
||||||
|
export const getProgressCategoryTemplate = (id: string | number): AxiosPromise<ProgressCategoryTemplateVO> => {
|
||||||
|
return request({
|
||||||
|
url: '/progress/progressCategoryTemplate/' + id,
|
||||||
|
method: 'get'
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增进度类别模版
|
||||||
|
* @param data
|
||||||
|
*/
|
||||||
|
export const addProgressCategoryTemplate = (data: ProgressCategoryTemplateForm) => {
|
||||||
|
return request({
|
||||||
|
url: '/progress/progressCategoryTemplate',
|
||||||
|
method: 'post',
|
||||||
|
data: data
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改进度类别模版
|
||||||
|
* @param data
|
||||||
|
*/
|
||||||
|
export const updateProgressCategoryTemplate = (data: ProgressCategoryTemplateForm) => {
|
||||||
|
return request({
|
||||||
|
url: '/progress/progressCategoryTemplate',
|
||||||
|
method: 'put',
|
||||||
|
data: data
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除进度类别模版
|
||||||
|
* @param id
|
||||||
|
*/
|
||||||
|
export const delProgressCategoryTemplate = (id: string | number | Array<string | number>) => {
|
||||||
|
return request({
|
||||||
|
url: '/progress/progressCategoryTemplate/' + id,
|
||||||
|
method: 'delete'
|
||||||
|
});
|
||||||
|
};
|
105
src/api/progress/progressCategoryTemplate/types.ts
Normal file
105
src/api/progress/progressCategoryTemplate/types.ts
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
export interface ProgressCategoryTemplateVO {
|
||||||
|
/**
|
||||||
|
* 类别名称
|
||||||
|
*/
|
||||||
|
name: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 计量方式(0无 1数量 2百分比)
|
||||||
|
*/
|
||||||
|
unitType: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 工作类型
|
||||||
|
*/
|
||||||
|
workType: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 项目id(0表示共用)
|
||||||
|
*/
|
||||||
|
projectId: string | number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 备注
|
||||||
|
*/
|
||||||
|
remark: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 子对象
|
||||||
|
*/
|
||||||
|
children: ProgressCategoryTemplateVO[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ProgressCategoryTemplateForm extends BaseEntity {
|
||||||
|
/**
|
||||||
|
* 主键id
|
||||||
|
*/
|
||||||
|
id?: string | number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 父类别id
|
||||||
|
*/
|
||||||
|
pid?: string | number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 类别名称
|
||||||
|
*/
|
||||||
|
name?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 计量方式(0无 1数量 2百分比)
|
||||||
|
*/
|
||||||
|
unitType?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 工作类型
|
||||||
|
*/
|
||||||
|
workType?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 项目id(0表示共用)
|
||||||
|
*/
|
||||||
|
projectId?: string | number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 备注
|
||||||
|
*/
|
||||||
|
remark?: string;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ProgressCategoryTemplateQuery {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 父类别id
|
||||||
|
*/
|
||||||
|
pid?: string | number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 类别名称
|
||||||
|
*/
|
||||||
|
name?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 计量方式(0无 1数量 2百分比)
|
||||||
|
*/
|
||||||
|
unitType?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 工作类型
|
||||||
|
*/
|
||||||
|
workType?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 项目id(0表示共用)
|
||||||
|
*/
|
||||||
|
projectId?: string | number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 日期范围参数
|
||||||
|
*/
|
||||||
|
params?: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -162,3 +162,4 @@
|
|||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
539
src/assets/iconfont/demo.css
Normal file
539
src/assets/iconfont/demo.css
Normal file
@ -0,0 +1,539 @@
|
|||||||
|
/* Logo 字体 */
|
||||||
|
@font-face {
|
||||||
|
font-family: "iconfont logo";
|
||||||
|
src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834');
|
||||||
|
src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834#iefix') format('embedded-opentype'),
|
||||||
|
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.woff?t=1545807318834') format('woff'),
|
||||||
|
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.ttf?t=1545807318834') format('truetype'),
|
||||||
|
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.svg?t=1545807318834#iconfont') format('svg');
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo {
|
||||||
|
font-family: "iconfont logo";
|
||||||
|
font-size: 160px;
|
||||||
|
font-style: normal;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* tabs */
|
||||||
|
.nav-tabs {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-tabs .nav-more {
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
height: 42px;
|
||||||
|
line-height: 42px;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
#tabs {
|
||||||
|
border-bottom: 1px solid #eee;
|
||||||
|
}
|
||||||
|
|
||||||
|
#tabs li {
|
||||||
|
cursor: pointer;
|
||||||
|
width: 100px;
|
||||||
|
height: 40px;
|
||||||
|
line-height: 40px;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 16px;
|
||||||
|
border-bottom: 2px solid transparent;
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
margin-bottom: -1px;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#tabs .active {
|
||||||
|
border-bottom-color: #f00;
|
||||||
|
color: #222;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-container .content {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 页面布局 */
|
||||||
|
.main {
|
||||||
|
padding: 30px 100px;
|
||||||
|
width: 960px;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.main .logo {
|
||||||
|
color: #333;
|
||||||
|
text-align: left;
|
||||||
|
margin-bottom: 30px;
|
||||||
|
line-height: 1;
|
||||||
|
height: 110px;
|
||||||
|
margin-top: -50px;
|
||||||
|
overflow: hidden;
|
||||||
|
*zoom: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.main .logo a {
|
||||||
|
font-size: 160px;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.helps {
|
||||||
|
margin-top: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.helps pre {
|
||||||
|
padding: 20px;
|
||||||
|
margin: 10px 0;
|
||||||
|
border: solid 1px #e7e1cd;
|
||||||
|
background-color: #fffdef;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon_lists {
|
||||||
|
width: 100% !important;
|
||||||
|
overflow: hidden;
|
||||||
|
*zoom: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon_lists li {
|
||||||
|
width: 100px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
margin-right: 20px;
|
||||||
|
text-align: center;
|
||||||
|
list-style: none !important;
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon_lists li .code-name {
|
||||||
|
line-height: 1.2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon_lists .icon {
|
||||||
|
display: block;
|
||||||
|
height: 100px;
|
||||||
|
line-height: 100px;
|
||||||
|
font-size: 42px;
|
||||||
|
margin: 10px auto;
|
||||||
|
color: #333;
|
||||||
|
-webkit-transition: font-size 0.25s linear, width 0.25s linear;
|
||||||
|
-moz-transition: font-size 0.25s linear, width 0.25s linear;
|
||||||
|
transition: font-size 0.25s linear, width 0.25s linear;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon_lists .icon:hover {
|
||||||
|
font-size: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon_lists .svg-icon {
|
||||||
|
/* 通过设置 font-size 来改变图标大小 */
|
||||||
|
width: 1em;
|
||||||
|
/* 图标和文字相邻时,垂直对齐 */
|
||||||
|
vertical-align: -0.15em;
|
||||||
|
/* 通过设置 color 来改变 SVG 的颜色/fill */
|
||||||
|
fill: currentColor;
|
||||||
|
/* path 和 stroke 溢出 viewBox 部分在 IE 下会显示
|
||||||
|
normalize.css 中也包含这行 */
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon_lists li .name,
|
||||||
|
.icon_lists li .code-name {
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* markdown 样式 */
|
||||||
|
.markdown {
|
||||||
|
color: #666;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 1.8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.highlight {
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown img {
|
||||||
|
vertical-align: middle;
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown h1 {
|
||||||
|
color: #404040;
|
||||||
|
font-weight: 500;
|
||||||
|
line-height: 40px;
|
||||||
|
margin-bottom: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown h2,
|
||||||
|
.markdown h3,
|
||||||
|
.markdown h4,
|
||||||
|
.markdown h5,
|
||||||
|
.markdown h6 {
|
||||||
|
color: #404040;
|
||||||
|
margin: 1.6em 0 0.6em 0;
|
||||||
|
font-weight: 500;
|
||||||
|
clear: both;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown h1 {
|
||||||
|
font-size: 28px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown h2 {
|
||||||
|
font-size: 22px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown h3 {
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown h4 {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown h5 {
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown h6 {
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown hr {
|
||||||
|
height: 1px;
|
||||||
|
border: 0;
|
||||||
|
background: #e9e9e9;
|
||||||
|
margin: 16px 0;
|
||||||
|
clear: both;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown p {
|
||||||
|
margin: 1em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown>p,
|
||||||
|
.markdown>blockquote,
|
||||||
|
.markdown>.highlight,
|
||||||
|
.markdown>ol,
|
||||||
|
.markdown>ul {
|
||||||
|
width: 80%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown ul>li {
|
||||||
|
list-style: circle;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown>ul li,
|
||||||
|
.markdown blockquote ul>li {
|
||||||
|
margin-left: 20px;
|
||||||
|
padding-left: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown>ul li p,
|
||||||
|
.markdown>ol li p {
|
||||||
|
margin: 0.6em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown ol>li {
|
||||||
|
list-style: decimal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown>ol li,
|
||||||
|
.markdown blockquote ol>li {
|
||||||
|
margin-left: 20px;
|
||||||
|
padding-left: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown code {
|
||||||
|
margin: 0 3px;
|
||||||
|
padding: 0 5px;
|
||||||
|
background: #eee;
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown strong,
|
||||||
|
.markdown b {
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown>table {
|
||||||
|
border-collapse: collapse;
|
||||||
|
border-spacing: 0px;
|
||||||
|
empty-cells: show;
|
||||||
|
border: 1px solid #e9e9e9;
|
||||||
|
width: 95%;
|
||||||
|
margin-bottom: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown>table th {
|
||||||
|
white-space: nowrap;
|
||||||
|
color: #333;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown>table th,
|
||||||
|
.markdown>table td {
|
||||||
|
border: 1px solid #e9e9e9;
|
||||||
|
padding: 8px 16px;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown>table th {
|
||||||
|
background: #F7F7F7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown blockquote {
|
||||||
|
font-size: 90%;
|
||||||
|
color: #999;
|
||||||
|
border-left: 4px solid #e9e9e9;
|
||||||
|
padding-left: 0.8em;
|
||||||
|
margin: 1em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown blockquote p {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown .anchor {
|
||||||
|
opacity: 0;
|
||||||
|
transition: opacity 0.3s ease;
|
||||||
|
margin-left: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown .waiting {
|
||||||
|
color: #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown h1:hover .anchor,
|
||||||
|
.markdown h2:hover .anchor,
|
||||||
|
.markdown h3:hover .anchor,
|
||||||
|
.markdown h4:hover .anchor,
|
||||||
|
.markdown h5:hover .anchor,
|
||||||
|
.markdown h6:hover .anchor {
|
||||||
|
opacity: 1;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown>br,
|
||||||
|
.markdown>p>br {
|
||||||
|
clear: both;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.hljs {
|
||||||
|
display: block;
|
||||||
|
background: white;
|
||||||
|
padding: 0.5em;
|
||||||
|
color: #333333;
|
||||||
|
overflow-x: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hljs-comment,
|
||||||
|
.hljs-meta {
|
||||||
|
color: #969896;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hljs-string,
|
||||||
|
.hljs-variable,
|
||||||
|
.hljs-template-variable,
|
||||||
|
.hljs-strong,
|
||||||
|
.hljs-emphasis,
|
||||||
|
.hljs-quote {
|
||||||
|
color: #df5000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hljs-keyword,
|
||||||
|
.hljs-selector-tag,
|
||||||
|
.hljs-type {
|
||||||
|
color: #a71d5d;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hljs-literal,
|
||||||
|
.hljs-symbol,
|
||||||
|
.hljs-bullet,
|
||||||
|
.hljs-attribute {
|
||||||
|
color: #0086b3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hljs-section,
|
||||||
|
.hljs-name {
|
||||||
|
color: #63a35c;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hljs-tag {
|
||||||
|
color: #333333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hljs-title,
|
||||||
|
.hljs-attr,
|
||||||
|
.hljs-selector-id,
|
||||||
|
.hljs-selector-class,
|
||||||
|
.hljs-selector-attr,
|
||||||
|
.hljs-selector-pseudo {
|
||||||
|
color: #795da3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hljs-addition {
|
||||||
|
color: #55a532;
|
||||||
|
background-color: #eaffea;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hljs-deletion {
|
||||||
|
color: #bd2c00;
|
||||||
|
background-color: #ffecec;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hljs-link {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 代码高亮 */
|
||||||
|
/* PrismJS 1.15.0
|
||||||
|
https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript */
|
||||||
|
/**
|
||||||
|
* prism.js default theme for JavaScript, CSS and HTML
|
||||||
|
* Based on dabblet (http://dabblet.com)
|
||||||
|
* @author Lea Verou
|
||||||
|
*/
|
||||||
|
code[class*="language-"],
|
||||||
|
pre[class*="language-"] {
|
||||||
|
color: black;
|
||||||
|
background: none;
|
||||||
|
text-shadow: 0 1px white;
|
||||||
|
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
|
||||||
|
text-align: left;
|
||||||
|
white-space: pre;
|
||||||
|
word-spacing: normal;
|
||||||
|
word-break: normal;
|
||||||
|
word-wrap: normal;
|
||||||
|
line-height: 1.5;
|
||||||
|
|
||||||
|
-moz-tab-size: 4;
|
||||||
|
-o-tab-size: 4;
|
||||||
|
tab-size: 4;
|
||||||
|
|
||||||
|
-webkit-hyphens: none;
|
||||||
|
-moz-hyphens: none;
|
||||||
|
-ms-hyphens: none;
|
||||||
|
hyphens: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre[class*="language-"]::-moz-selection,
|
||||||
|
pre[class*="language-"] ::-moz-selection,
|
||||||
|
code[class*="language-"]::-moz-selection,
|
||||||
|
code[class*="language-"] ::-moz-selection {
|
||||||
|
text-shadow: none;
|
||||||
|
background: #b3d4fc;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre[class*="language-"]::selection,
|
||||||
|
pre[class*="language-"] ::selection,
|
||||||
|
code[class*="language-"]::selection,
|
||||||
|
code[class*="language-"] ::selection {
|
||||||
|
text-shadow: none;
|
||||||
|
background: #b3d4fc;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media print {
|
||||||
|
|
||||||
|
code[class*="language-"],
|
||||||
|
pre[class*="language-"] {
|
||||||
|
text-shadow: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Code blocks */
|
||||||
|
pre[class*="language-"] {
|
||||||
|
padding: 1em;
|
||||||
|
margin: .5em 0;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
:not(pre)>code[class*="language-"],
|
||||||
|
pre[class*="language-"] {
|
||||||
|
background: #f5f2f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Inline code */
|
||||||
|
:not(pre)>code[class*="language-"] {
|
||||||
|
padding: .1em;
|
||||||
|
border-radius: .3em;
|
||||||
|
white-space: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.comment,
|
||||||
|
.token.prolog,
|
||||||
|
.token.doctype,
|
||||||
|
.token.cdata {
|
||||||
|
color: slategray;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.punctuation {
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.namespace {
|
||||||
|
opacity: .7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.property,
|
||||||
|
.token.tag,
|
||||||
|
.token.boolean,
|
||||||
|
.token.number,
|
||||||
|
.token.constant,
|
||||||
|
.token.symbol,
|
||||||
|
.token.deleted {
|
||||||
|
color: #905;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.selector,
|
||||||
|
.token.attr-name,
|
||||||
|
.token.string,
|
||||||
|
.token.char,
|
||||||
|
.token.builtin,
|
||||||
|
.token.inserted {
|
||||||
|
color: #690;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.operator,
|
||||||
|
.token.entity,
|
||||||
|
.token.url,
|
||||||
|
.language-css .token.string,
|
||||||
|
.style .token.string {
|
||||||
|
color: #9a6e3a;
|
||||||
|
background: hsla(0, 0%, 100%, .5);
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.atrule,
|
||||||
|
.token.attr-value,
|
||||||
|
.token.keyword {
|
||||||
|
color: #07a;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.function,
|
||||||
|
.token.class-name {
|
||||||
|
color: #DD4A68;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.regex,
|
||||||
|
.token.important,
|
||||||
|
.token.variable {
|
||||||
|
color: #e90;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.important,
|
||||||
|
.token.bold {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.italic {
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.entity {
|
||||||
|
cursor: help;
|
||||||
|
}
|
211
src/assets/iconfont/demo_index.html
Normal file
211
src/assets/iconfont/demo_index.html
Normal file
@ -0,0 +1,211 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8"/>
|
||||||
|
<title>iconfont Demo</title>
|
||||||
|
<link rel="shortcut icon" href="//img.alicdn.com/imgextra/i4/O1CN01Z5paLz1O0zuCC7osS_!!6000000001644-55-tps-83-82.svg" type="image/x-icon"/>
|
||||||
|
<link rel="icon" type="image/svg+xml" href="//img.alicdn.com/imgextra/i4/O1CN01Z5paLz1O0zuCC7osS_!!6000000001644-55-tps-83-82.svg"/>
|
||||||
|
<link rel="stylesheet" href="https://g.alicdn.com/thx/cube/1.3.2/cube.min.css">
|
||||||
|
<link rel="stylesheet" href="demo.css">
|
||||||
|
<link rel="stylesheet" href="iconfont.css">
|
||||||
|
<script src="iconfont.js"></script>
|
||||||
|
<!-- jQuery -->
|
||||||
|
<script src="https://a1.alicdn.com/oss/uploads/2018/12/26/7bfddb60-08e8-11e9-9b04-53e73bb6408b.js"></script>
|
||||||
|
<!-- 代码高亮 -->
|
||||||
|
<script src="https://a1.alicdn.com/oss/uploads/2018/12/26/a3f714d0-08e6-11e9-8a15-ebf944d7534c.js"></script>
|
||||||
|
<style>
|
||||||
|
.main .logo {
|
||||||
|
margin-top: 0;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.main .logo a {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.main .logo .sub-title {
|
||||||
|
margin-left: 0.5em;
|
||||||
|
font-size: 22px;
|
||||||
|
color: #fff;
|
||||||
|
background: linear-gradient(-45deg, #3967FF, #B500FE);
|
||||||
|
-webkit-background-clip: text;
|
||||||
|
-webkit-text-fill-color: transparent;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="main">
|
||||||
|
<h1 class="logo"><a href="https://www.iconfont.cn/" title="iconfont 首页" target="_blank">
|
||||||
|
<img width="200" src="https://img.alicdn.com/imgextra/i3/O1CN01Mn65HV1FfSEzR6DKv_!!6000000000514-55-tps-228-59.svg">
|
||||||
|
|
||||||
|
</a></h1>
|
||||||
|
<div class="nav-tabs">
|
||||||
|
<ul id="tabs" class="dib-box">
|
||||||
|
<li class="dib active"><span>Unicode</span></li>
|
||||||
|
<li class="dib"><span>Font class</span></li>
|
||||||
|
<li class="dib"><span>Symbol</span></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<a href="https://www.iconfont.cn/manage/index?manage_type=myprojects&projectId=4936044" target="_blank" class="nav-more">查看项目</a>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="tab-container">
|
||||||
|
<div class="content unicode" style="display: block;">
|
||||||
|
<ul class="icon_lists dib-box">
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<span class="icon iconfont"></span>
|
||||||
|
<div class="name">问号</div>
|
||||||
|
<div class="code-name">&#xe72d;</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
<div class="article markdown">
|
||||||
|
<h2 id="unicode-">Unicode 引用</h2>
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<p>Unicode 是字体在网页端最原始的应用方式,特点是:</p>
|
||||||
|
<ul>
|
||||||
|
<li>支持按字体的方式去动态调整图标大小,颜色等等。</li>
|
||||||
|
<li>默认情况下不支持多色,直接添加多色图标会自动去色。</li>
|
||||||
|
</ul>
|
||||||
|
<blockquote>
|
||||||
|
<p>注意:新版 iconfont 支持两种方式引用多色图标:SVG symbol 引用方式和彩色字体图标模式。(使用彩色字体图标需要在「编辑项目」中开启「彩色」选项后并重新生成。)</p>
|
||||||
|
</blockquote>
|
||||||
|
<p>Unicode 使用步骤如下:</p>
|
||||||
|
<h3 id="-font-face">第一步:拷贝项目下面生成的 <code>@font-face</code></h3>
|
||||||
|
<pre><code class="language-css"
|
||||||
|
>@font-face {
|
||||||
|
font-family: 'iconfont';
|
||||||
|
src: url('iconfont.woff2?t=1748505165241') format('woff2'),
|
||||||
|
url('iconfont.woff?t=1748505165241') format('woff'),
|
||||||
|
url('iconfont.ttf?t=1748505165241') format('truetype');
|
||||||
|
}
|
||||||
|
</code></pre>
|
||||||
|
<h3 id="-iconfont-">第二步:定义使用 iconfont 的样式</h3>
|
||||||
|
<pre><code class="language-css"
|
||||||
|
>.iconfont {
|
||||||
|
font-family: "iconfont" !important;
|
||||||
|
font-size: 16px;
|
||||||
|
font-style: normal;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
}
|
||||||
|
</code></pre>
|
||||||
|
<h3 id="-">第三步:挑选相应图标并获取字体编码,应用于页面</h3>
|
||||||
|
<pre>
|
||||||
|
<code class="language-html"
|
||||||
|
><span class="iconfont">&#x33;</span>
|
||||||
|
</code></pre>
|
||||||
|
<blockquote>
|
||||||
|
<p>"iconfont" 是你项目下的 font-family。可以通过编辑项目查看,默认是 "iconfont"。</p>
|
||||||
|
</blockquote>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="content font-class">
|
||||||
|
<ul class="icon_lists dib-box">
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<span class="icon iconfont icon-wenhao"></span>
|
||||||
|
<div class="name">
|
||||||
|
问号
|
||||||
|
</div>
|
||||||
|
<div class="code-name">.icon-wenhao
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
<div class="article markdown">
|
||||||
|
<h2 id="font-class-">font-class 引用</h2>
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<p>font-class 是 Unicode 使用方式的一种变种,主要是解决 Unicode 书写不直观,语意不明确的问题。</p>
|
||||||
|
<p>与 Unicode 使用方式相比,具有如下特点:</p>
|
||||||
|
<ul>
|
||||||
|
<li>相比于 Unicode 语意明确,书写更直观。可以很容易分辨这个 icon 是什么。</li>
|
||||||
|
<li>因为使用 class 来定义图标,所以当要替换图标时,只需要修改 class 里面的 Unicode 引用。</li>
|
||||||
|
</ul>
|
||||||
|
<p>使用步骤如下:</p>
|
||||||
|
<h3 id="-fontclass-">第一步:引入项目下面生成的 fontclass 代码:</h3>
|
||||||
|
<pre><code class="language-html"><link rel="stylesheet" href="./iconfont.css">
|
||||||
|
</code></pre>
|
||||||
|
<h3 id="-">第二步:挑选相应图标并获取类名,应用于页面:</h3>
|
||||||
|
<pre><code class="language-html"><span class="iconfont icon-xxx"></span>
|
||||||
|
</code></pre>
|
||||||
|
<blockquote>
|
||||||
|
<p>"
|
||||||
|
iconfont" 是你项目下的 font-family。可以通过编辑项目查看,默认是 "iconfont"。</p>
|
||||||
|
</blockquote>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="content symbol">
|
||||||
|
<ul class="icon_lists dib-box">
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<svg class="icon svg-icon" aria-hidden="true">
|
||||||
|
<use xlink:href="#icon-wenhao"></use>
|
||||||
|
</svg>
|
||||||
|
<div class="name">问号</div>
|
||||||
|
<div class="code-name">#icon-wenhao</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
<div class="article markdown">
|
||||||
|
<h2 id="symbol-">Symbol 引用</h2>
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<p>这是一种全新的使用方式,应该说这才是未来的主流,也是平台目前推荐的用法。相关介绍可以参考这篇<a href="">文章</a>
|
||||||
|
这种用法其实是做了一个 SVG 的集合,与另外两种相比具有如下特点:</p>
|
||||||
|
<ul>
|
||||||
|
<li>支持多色图标了,不再受单色限制。</li>
|
||||||
|
<li>通过一些技巧,支持像字体那样,通过 <code>font-size</code>, <code>color</code> 来调整样式。</li>
|
||||||
|
<li>兼容性较差,支持 IE9+,及现代浏览器。</li>
|
||||||
|
<li>浏览器渲染 SVG 的性能一般,还不如 png。</li>
|
||||||
|
</ul>
|
||||||
|
<p>使用步骤如下:</p>
|
||||||
|
<h3 id="-symbol-">第一步:引入项目下面生成的 symbol 代码:</h3>
|
||||||
|
<pre><code class="language-html"><script src="./iconfont.js"></script>
|
||||||
|
</code></pre>
|
||||||
|
<h3 id="-css-">第二步:加入通用 CSS 代码(引入一次就行):</h3>
|
||||||
|
<pre><code class="language-html"><style>
|
||||||
|
.icon {
|
||||||
|
width: 1em;
|
||||||
|
height: 1em;
|
||||||
|
vertical-align: -0.15em;
|
||||||
|
fill: currentColor;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</code></pre>
|
||||||
|
<h3 id="-">第三步:挑选相应图标并获取类名,应用于页面:</h3>
|
||||||
|
<pre><code class="language-html"><svg class="icon" aria-hidden="true">
|
||||||
|
<use xlink:href="#icon-xxx"></use>
|
||||||
|
</svg>
|
||||||
|
</code></pre>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<script>
|
||||||
|
$(document).ready(function () {
|
||||||
|
$('.tab-container .content:first').show()
|
||||||
|
|
||||||
|
$('#tabs li').click(function (e) {
|
||||||
|
var tabContent = $('.tab-container .content')
|
||||||
|
var index = $(this).index()
|
||||||
|
|
||||||
|
if ($(this).hasClass('active')) {
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
$('#tabs li').removeClass('active')
|
||||||
|
$(this).addClass('active')
|
||||||
|
|
||||||
|
tabContent.hide().eq(index).fadeIn()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
19
src/assets/iconfont/iconfont.css
Normal file
19
src/assets/iconfont/iconfont.css
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
@font-face {
|
||||||
|
font-family: "iconfont"; /* Project id 4936044 */
|
||||||
|
src: url('iconfont.woff2?t=1748505165241') format('woff2'),
|
||||||
|
url('iconfont.woff?t=1748505165241') format('woff'),
|
||||||
|
url('iconfont.ttf?t=1748505165241') format('truetype');
|
||||||
|
}
|
||||||
|
|
||||||
|
.iconfont {
|
||||||
|
font-family: "iconfont" !important;
|
||||||
|
font-size: 16px;
|
||||||
|
font-style: normal;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-wenhao:before {
|
||||||
|
content: "\e72d";
|
||||||
|
}
|
||||||
|
|
1
src/assets/iconfont/iconfont.js
Normal file
1
src/assets/iconfont/iconfont.js
Normal file
@ -0,0 +1 @@
|
|||||||
|
window._iconfont_svg_string_4936044='<svg><symbol id="icon-wenhao" viewBox="0 0 1024 1024"><path d="M463.99957 784.352211c0 26.509985 21.490445 48.00043 48.00043 48.00043s48.00043-21.490445 48.00043-48.00043c0-26.509985-21.490445-48.00043-48.00043-48.00043S463.99957 757.842226 463.99957 784.352211z" fill="#575B66" ></path><path d="M512 960c-247.039484 0-448-200.960516-448-448S264.960516 64 512 64 960 264.960516 960 512 759.039484 960 512 960zM512 128.287273c-211.584464 0-383.712727 172.128262-383.712727 383.712727 0 211.551781 172.128262 383.712727 383.712727 383.712727 211.551781 0 383.712727-172.159226 383.712727-383.712727C895.712727 300.415536 723.551781 128.287273 512 128.287273z" fill="#575B66" ></path><path d="M512 673.695256c-17.664722 0-32.00086-14.336138-32.00086-31.99914l0-54.112297c0-52.352533 39.999785-92.352318 75.32751-127.647359 25.887273-25.919957 52.67249-52.67249 52.67249-74.016718 0-53.343368-43.07206-96.735385-95.99914-96.735385-53.823303 0-95.99914 41.535923-95.99914 94.559333 0 17.664722-14.336138 31.99914-32.00086 31.99914s-32.00086-14.336138-32.00086-31.99914c0-87.423948 71.775299-158.559333 160.00086-158.559333s160.00086 72.095256 160.00086 160.735385c0 47.904099-36.32028 84.191695-71.424378 119.295794-27.839699 27.776052-56.575622 56.511974-56.575622 82.3356l0 54.112297C544.00086 659.328155 529.664722 673.695256 512 673.695256z" fill="#575B66" ></path></symbol></svg>',(n=>{var t=(e=(e=document.getElementsByTagName("script"))[e.length-1]).getAttribute("data-injectcss"),e=e.getAttribute("data-disable-injectsvg");if(!e){var i,o,c,d,s,a=function(t,e){e.parentNode.insertBefore(t,e)};if(t&&!n.__iconfont__svg__cssinject__){n.__iconfont__svg__cssinject__=!0;try{document.write("<style>.svgfont {display: inline-block;width: 1em;height: 1em;fill: currentColor;vertical-align: -0.1em;font-size:16px;}</style>")}catch(t){console&&console.log(t)}}i=function(){var t,e=document.createElement("div");e.innerHTML=n._iconfont_svg_string_4936044,(e=e.getElementsByTagName("svg")[0])&&(e.setAttribute("aria-hidden","true"),e.style.position="absolute",e.style.width=0,e.style.height=0,e.style.overflow="hidden",e=e,(t=document.body).firstChild?a(e,t.firstChild):t.appendChild(e))},document.addEventListener?~["complete","loaded","interactive"].indexOf(document.readyState)?setTimeout(i,0):(o=function(){document.removeEventListener("DOMContentLoaded",o,!1),i()},document.addEventListener("DOMContentLoaded",o,!1)):document.attachEvent&&(c=i,d=n.document,s=!1,r(),d.onreadystatechange=function(){"complete"==d.readyState&&(d.onreadystatechange=null,l())})}function l(){s||(s=!0,c())}function r(){try{d.documentElement.doScroll("left")}catch(t){return void setTimeout(r,50)}l()}})(window);
|
16
src/assets/iconfont/iconfont.json
Normal file
16
src/assets/iconfont/iconfont.json
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"id": "4936044",
|
||||||
|
"name": "no name",
|
||||||
|
"font_family": "iconfont",
|
||||||
|
"css_prefix_text": "icon-",
|
||||||
|
"description": "",
|
||||||
|
"glyphs": [
|
||||||
|
{
|
||||||
|
"icon_id": "577319",
|
||||||
|
"name": "问号",
|
||||||
|
"font_class": "wenhao",
|
||||||
|
"unicode": "e72d",
|
||||||
|
"unicode_decimal": 59181
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
BIN
src/assets/iconfont/iconfont.ttf
Normal file
BIN
src/assets/iconfont/iconfont.ttf
Normal file
Binary file not shown.
BIN
src/assets/iconfont/iconfont.woff
Normal file
BIN
src/assets/iconfont/iconfont.woff
Normal file
Binary file not shown.
BIN
src/assets/iconfont/iconfont.woff2
Normal file
BIN
src/assets/iconfont/iconfont.woff2
Normal file
Binary file not shown.
@ -139,28 +139,37 @@ const handlePosition = (data: any, node) => {
|
|||||||
|
|
||||||
map.getView().setCenter(centerPosition.value);
|
map.getView().setCenter(centerPosition.value);
|
||||||
};
|
};
|
||||||
const handleCheckChange = (data: any, bool) => {
|
const handleCheckChange = (data: any, bool: boolean) => {
|
||||||
// 处理树形结构的选中变化
|
|
||||||
let features = treeData.value[data.index].features;
|
|
||||||
if (isMenuVisible.value) isMenuVisible.value = false;
|
if (isMenuVisible.value) isMenuVisible.value = false;
|
||||||
|
|
||||||
|
const features = treeData.value[data.index].features;
|
||||||
|
|
||||||
if (bool) {
|
if (bool) {
|
||||||
if (!layerData[features[0].properties.id]) {
|
|
||||||
features.forEach((item: any) => {
|
features.forEach((item: any) => {
|
||||||
creatPoint(item.geometry.coordinates, item.geometry.type, item.geometry.id, item.properties.text);
|
const fid = item.geometry.id;
|
||||||
});
|
|
||||||
} else {
|
// 没创建过就先创建
|
||||||
features.forEach((item: any) => {
|
if (!featureMap[fid]) {
|
||||||
map.addLayer(layerData[item.geometry.id]);
|
creatPoint(item.geometry.coordinates, item.geometry.type, fid, item.properties.text);
|
||||||
});
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
features.forEach((item, index) => {
|
|
||||||
map.removeLayer(layerData[item.geometry.id]);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// creatPoint(fromLonLat(data.geometry.coordinates), data.geometry.type);
|
// 添加到共享 source 中(避免重复添加)
|
||||||
|
const feature = featureMap[fid];
|
||||||
|
if (!sharedSource.hasFeature(feature)) {
|
||||||
|
sharedSource.addFeature(feature);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
features.forEach((item: any) => {
|
||||||
|
const fid = item.geometry.id;
|
||||||
|
const feature = featureMap[fid];
|
||||||
|
if (feature && sharedSource.hasFeature(feature)) {
|
||||||
|
sharedSource.removeFeature(feature);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
function initOLMap() {
|
function initOLMap() {
|
||||||
// 创造地图实例
|
// 创造地图实例
|
||||||
map = new Map({
|
map = new Map({
|
||||||
@ -246,58 +255,57 @@ function convertStrToNum(arr) {
|
|||||||
* @param {*} id 唯一id
|
* @param {*} id 唯一id
|
||||||
* @param {*} name 名称
|
* @param {*} name 名称
|
||||||
* */
|
* */
|
||||||
|
// 共享 source 和图层(全局一次性创建)
|
||||||
|
const sharedSource = new VectorSource();
|
||||||
|
const sharedLayer = new VectorLayer({
|
||||||
|
source: sharedSource,
|
||||||
|
renderMode: 'image' // 提高渲染性能
|
||||||
|
} as any);
|
||||||
|
|
||||||
|
// id => Feature 映射表
|
||||||
|
const featureMap: Record<string, Feature> = {};
|
||||||
|
|
||||||
const creatPoint = (pointObj: Array<any>, type: string, id: string, name?: string) => {
|
const creatPoint = (pointObj: Array<any>, type: string, id: string, name?: string) => {
|
||||||
// 创建多边形的几何对象
|
let geometry;
|
||||||
let polygon;
|
|
||||||
if (type === 'Point') {
|
if (type === 'Point') {
|
||||||
polygon = new Point(fromLonLat(pointObj));
|
geometry = new Point(fromLonLat(pointObj));
|
||||||
} else if (type === 'LineString') {
|
} else if (type === 'LineString') {
|
||||||
const lineStringData = pointObj.map((arr: any) => fromLonLat(arr));
|
const coords = pointObj.map((arr: any) => fromLonLat(arr));
|
||||||
polygon = new Polygon([lineStringData]);
|
// 注意:这里虽然是 LineString 类型,但数据实际表示的是闭合面
|
||||||
|
geometry = new Polygon([coords]);
|
||||||
} else {
|
} else {
|
||||||
const polygonData = pointObj.map((arr: any) => arr.map((i: any) => fromLonLat(i)));
|
const coords = pointObj.map((arr: any) => arr.map((i: any) => fromLonLat(i)));
|
||||||
polygon = new Polygon(polygonData);
|
geometry = new Polygon(coords);
|
||||||
}
|
}
|
||||||
// 创建特征(Feature)
|
|
||||||
let polygonFeature = new Feature({
|
const feature = new Feature({ geometry });
|
||||||
geometry: polygon
|
|
||||||
});
|
|
||||||
|
|
||||||
const pointStyle = new Style({
|
const pointStyle = new Style({
|
||||||
image: new Circle({
|
image: new Circle({
|
||||||
radius: 2,
|
radius: 2,
|
||||||
fill: new Fill({
|
fill: new Fill({ color: 'red' })
|
||||||
color: 'red'
|
|
||||||
})
|
|
||||||
}),
|
}),
|
||||||
text: new Text({
|
text: new Text({
|
||||||
font: '12px Microsoft YaHei',
|
font: '12px Microsoft YaHei',
|
||||||
text: name,
|
text: name,
|
||||||
scale: 1,
|
scale: 1,
|
||||||
fill: new Fill({
|
fill: new Fill({ color: '#7bdd63' })
|
||||||
color: '#7bdd63'
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
const polygonStyle = new Style({
|
const polygonStyle = new Style({
|
||||||
stroke: new Stroke({
|
stroke: new Stroke({
|
||||||
color: type === 'LineString' ? 'skyblue' : 'purple', // 多边形边界线的颜色
|
color: type === 'LineString' ? 'skyblue' : 'purple',
|
||||||
width: 2 // 多边形边界线的宽度
|
width: 2
|
||||||
}),
|
}),
|
||||||
fill: new Fill({
|
fill: new Fill({ color: 'transparent' })
|
||||||
color: 'transparent' // 多边形填充颜色,这里设置为半透明红色
|
|
||||||
})
|
|
||||||
});
|
});
|
||||||
// 设置多边形的样式(Style)
|
|
||||||
polygonFeature.setStyle(type === 'Point' ? pointStyle : polygonStyle);
|
|
||||||
// 创建和添加特征到源(Source)
|
|
||||||
let source = new VectorSource();
|
|
||||||
source.addFeature(polygonFeature);
|
|
||||||
// 创建图层并设置源(Layer)
|
|
||||||
layerData[id] = new VectorLayer();
|
|
||||||
layerData[id].setSource(source);
|
|
||||||
|
|
||||||
map.addLayer(layerData[id]);
|
feature.setStyle(type === 'Point' ? pointStyle : polygonStyle);
|
||||||
|
|
||||||
|
// 缓存 feature(用于后续判断)
|
||||||
|
featureMap[id] = feature;
|
||||||
};
|
};
|
||||||
|
|
||||||
// 控制菜单是否显示
|
// 控制菜单是否显示
|
||||||
@ -490,6 +498,7 @@ watch(
|
|||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
// 地图初始化
|
// 地图初始化
|
||||||
initOLMap();
|
initOLMap();
|
||||||
|
map.addLayer(sharedLayer);
|
||||||
// creatPoint(
|
// creatPoint(
|
||||||
// [
|
// [
|
||||||
// [
|
// [
|
||||||
|
@ -2,6 +2,7 @@ import { createApp } from 'vue';
|
|||||||
// global css
|
// global css
|
||||||
import 'virtual:uno.css';
|
import 'virtual:uno.css';
|
||||||
import '@/assets/styles/index.scss';
|
import '@/assets/styles/index.scss';
|
||||||
|
import '@/assets/iconfont/iconfont.css';
|
||||||
import 'element-plus/theme-chalk/dark/css-vars.css';
|
import 'element-plus/theme-chalk/dark/css-vars.css';
|
||||||
|
|
||||||
// App、router、store
|
// App、router、store
|
||||||
|
@ -103,7 +103,12 @@ export const constantRoutes: RouteRecordRaw[] = [
|
|||||||
path: '/drone',
|
path: '/drone',
|
||||||
component: () => import('@/views/drone/index.vue'),
|
component: () => import('@/views/drone/index.vue'),
|
||||||
hidden: true
|
hidden: true
|
||||||
}
|
},
|
||||||
|
{
|
||||||
|
path: '/progress/progressPaper',
|
||||||
|
component: () => import('@/views/progress/progressPaper/index.vue'),
|
||||||
|
hidden: true
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
// 动态路由,基于用户权限动态去加载
|
// 动态路由,基于用户权限动态去加载
|
||||||
|
@ -1,8 +1,16 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="daily_paper">
|
<div class="daily_paper">
|
||||||
<el-dialog v-model="isShowDialog" @close="onCancel" width="1000px" :close-on-click-modal="false" :destroy-on-close="true">
|
<el-dialog
|
||||||
|
v-model="isShowDialog"
|
||||||
|
@close="onCancel"
|
||||||
|
width="1000px"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
:destroy-on-close="true"
|
||||||
|
:lock-scroll="false"
|
||||||
|
:append-to-body="false"
|
||||||
|
>
|
||||||
<template #header>
|
<template #header>
|
||||||
<div v-drag="['.daily_paper .el-dialog', '.daily_paper .el-dialog__header']" style="font-size: 18px">{{ infoDetail.name }} 日报填写</div>
|
<div style="font-size: 18px">{{ infoDetail.name }} 日报填写</div>
|
||||||
</template>
|
</template>
|
||||||
<div class="box">
|
<div class="box">
|
||||||
<div class="box-left">
|
<div class="box-left">
|
||||||
@ -197,6 +205,32 @@ const clickOpen = (row: any) => {
|
|||||||
|
|
||||||
defineExpose({ openDialog });
|
defineExpose({ openDialog });
|
||||||
const emit = defineEmits(['getProgressList']);
|
const emit = defineEmits(['getProgressList']);
|
||||||
|
|
||||||
|
let scrollTop = 0;
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => isShowDialog.value,
|
||||||
|
(visible) => {
|
||||||
|
if (visible) {
|
||||||
|
scrollTop = window.scrollY || document.documentElement.scrollTop;
|
||||||
|
const scrollbarWidth = window.innerWidth - document.documentElement.clientWidth;
|
||||||
|
|
||||||
|
document.body.style.position = 'fixed';
|
||||||
|
document.body.style.top = `-${scrollTop}px`;
|
||||||
|
document.body.style.width = '100%';
|
||||||
|
document.body.style.paddingRight = `${scrollbarWidth}px`; // 👈 补偿滚动条宽度
|
||||||
|
} else {
|
||||||
|
document.body.style.position = '';
|
||||||
|
document.body.style.top = '';
|
||||||
|
document.body.style.width = '';
|
||||||
|
document.body.style.paddingRight = ''; // 👈 恢复
|
||||||
|
|
||||||
|
nextTick(() => {
|
||||||
|
window.scrollTo(0, scrollTop);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
@ -1,6 +1,14 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="daily-paper-count">
|
<div class="daily-paper-count">
|
||||||
<el-dialog v-model="isShowDialog" @close="onCancel" width="65vw" :close-on-click-modal="false" :destroy-on-close="true">
|
<el-dialog
|
||||||
|
v-model="isShowDialog"
|
||||||
|
@close="onCancel"
|
||||||
|
width="70vw"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
:destroy-on-close="true"
|
||||||
|
:lock-scroll="false"
|
||||||
|
:append-to-body="false"
|
||||||
|
>
|
||||||
<template #header>
|
<template #header>
|
||||||
<div v-drag="['.daily-paper-count .el-dialog', '.daily-paper-count .el-dialog__header']" style="font-size: 18px">
|
<div v-drag="['.daily-paper-count .el-dialog', '.daily-paper-count .el-dialog__header']" style="font-size: 18px">
|
||||||
{{ infoDetail.name }} 日报填写
|
{{ infoDetail.name }} 日报填写
|
||||||
@ -24,23 +32,23 @@
|
|||||||
<div style="margin-left: 45px" m="4">
|
<div style="margin-left: 45px" m="4">
|
||||||
<el-table
|
<el-table
|
||||||
:border="true"
|
:border="true"
|
||||||
:data="propsRow.detail"
|
:data="propsRow.detailList"
|
||||||
:header-cell-style="{ 'text-align': 'center' }"
|
:header-cell-style="{ 'text-align': 'center' }"
|
||||||
:cell-style="{ 'text-align': 'center' }"
|
:cell-style="{ 'text-align': 'center' }"
|
||||||
highlight-current-row
|
highlight-current-row
|
||||||
>
|
>
|
||||||
<el-table-column label="序号" type="index" width="60px" />
|
<el-table-column label="序号" type="index" width="60px" />
|
||||||
<el-table-column label="计划日期" prop="date" />
|
<el-table-column label="计划日期" prop="date" />
|
||||||
<el-table-column label="数量" prop="planNum" width="60" />
|
<el-table-column label="数量" prop="planNumber" width="60" />
|
||||||
<el-table-column label="完成量" prop="finishedNum" width="60" />
|
<el-table-column label="完成量" prop="finishedNumber" width="70" />
|
||||||
<el-table-column label="AI填报" prop="autoFill" width="60" />
|
<el-table-column label="AI填报" prop="aiFill" width="70" />
|
||||||
<el-table-column label="操作" class-name="small-padding" width="200px" fixed="right">
|
<el-table-column label="操作" class-name="small-padding" width="170px" fixed="right">
|
||||||
<template #default="{ row: scopeRow, $index }">
|
<template #default="{ row: scopeRow, $index }">
|
||||||
<el-button type="primary" link @click="handleDayAdd(scopeRow, propsRow)">
|
<el-button type="primary" link @click="handleDayAdd(scopeRow, propsRow)">
|
||||||
<el-icon><ele-Plus /></el-icon>日报
|
<el-icon><Plus /></el-icon>日报
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button type="success" link @click="handleView(scopeRow, propsRow)">
|
<el-button type="success" link @click="handleView(scopeRow, propsRow)">
|
||||||
<el-icon><ele-View /></el-icon>查看
|
<el-icon><View /></el-icon>查看
|
||||||
</el-button>
|
</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
@ -49,8 +57,8 @@
|
|||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="序号" type="index" :index="indexMethod" width="60px" />
|
<el-table-column label="序号" type="index" :index="indexMethod" width="60px" />
|
||||||
<el-table-column label="计划数量" prop="planNum" min-width="100px" />
|
<el-table-column label="计划数量" prop="planNumber" min-width="100px" />
|
||||||
<el-table-column label="完成数量" prop="finishedNum" min-width="100px" />
|
<el-table-column label="完成数量" prop="finishedNumber" min-width="100px" />
|
||||||
<el-table-column label="延期量" min-width="100px">
|
<el-table-column label="延期量" min-width="100px">
|
||||||
<template #default="{ row: scopeRow }">
|
<template #default="{ row: scopeRow }">
|
||||||
<el-tag :type="filterW(scopeRow) ? 'danger' : 'success'">
|
<el-tag :type="filterW(scopeRow) ? 'danger' : 'success'">
|
||||||
@ -58,10 +66,10 @@
|
|||||||
</el-tag>
|
</el-tag>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="AI填报" prop="autoFill" min-width="100px" />
|
<el-table-column label="AI填报" prop="aiFill" min-width="100px" />
|
||||||
<el-table-column label="开始时间" min-width="100px">
|
<el-table-column label="开始时间" min-width="100px">
|
||||||
<template #default="{ row: scopeRow }">
|
<template #default="{ row: scopeRow }">
|
||||||
<span>{{ scopeRow.startAt.split(' ')[0] }}</span>
|
<span>{{ scopeRow.startDate.split(' ')[0] }}</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
@ -73,13 +81,14 @@
|
|||||||
@pagination="getWorkList"
|
@pagination="getWorkList"
|
||||||
layout="total, sizes, prev, pager, next"
|
layout="total, sizes, prev, pager, next"
|
||||||
:isSmall="5"
|
:isSmall="5"
|
||||||
|
class="float-left mt-4.5!"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="box_right" v-if="showDayWork">
|
<div class="box_right" v-if="showDayWork">
|
||||||
<div class="time_submit">
|
<div class="time_submit">
|
||||||
<span>{{ formDetail.submitTime }}</span>
|
<span>{{ formDetail.submitTime }}</span>
|
||||||
<el-button type="primary" :disabled="!checkedList.length || flag" @click="onUploadDaily" size="large">
|
<el-button type="primary" :disabled="!checkedList.length || flag" @click="onUploadDaily" size="small">
|
||||||
<el-icon><ele-Upload /></el-icon>提交日报
|
<el-icon><Upload /></el-icon>提交日报
|
||||||
</el-button>
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
<el-table
|
<el-table
|
||||||
@ -97,14 +106,14 @@
|
|||||||
<el-table-column label="状态" align="center" min-width="100px">
|
<el-table-column label="状态" align="center" min-width="100px">
|
||||||
<template #default="{ row: scopeRow }">
|
<template #default="{ row: scopeRow }">
|
||||||
<el-tag :type="typeList[scopeRow.status]">
|
<el-tag :type="typeList[scopeRow.status]">
|
||||||
{{ filterStatus(scopeRow.status) }}
|
{{ filterStatus(Number(scopeRow.status)) }}
|
||||||
</el-tag>
|
</el-tag>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
<pagination
|
<pagination
|
||||||
v-show="detailTotal > 0"
|
v-show="1"
|
||||||
:total="detailTotal"
|
:total="detailTotal"
|
||||||
v-model:page="detailQueryParams.pageNum"
|
v-model:page="detailQueryParams.pageNum"
|
||||||
v-model:limit="detailQueryParams.pageSize"
|
v-model:limit="detailQueryParams.pageSize"
|
||||||
@ -116,8 +125,8 @@
|
|||||||
<div class="box_right" v-else>
|
<div class="box_right" v-else>
|
||||||
<div class="time_submit">
|
<div class="time_submit">
|
||||||
<span>{{ formDetail.submitTime }}</span>
|
<span>{{ formDetail.submitTime }}</span>
|
||||||
<el-button type="danger" :disabled="single" @click="handleRemove(null)" size="large">
|
<el-button type="danger" :disabled="single" @click="handleRemove(null)" size="small">
|
||||||
<el-icon><ele-SemiSelect /></el-icon>批量移除
|
<el-icon><Minus /></el-icon>批量移除
|
||||||
</el-button>
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
<el-table
|
<el-table
|
||||||
@ -134,14 +143,14 @@
|
|||||||
<el-table-column label="编号" align="center" prop="name" min-width="100px" />
|
<el-table-column label="编号" align="center" prop="name" min-width="100px" />
|
||||||
<el-table-column label="填报方式" align="center" prop="status" min-width="100px">
|
<el-table-column label="填报方式" align="center" prop="status" min-width="100px">
|
||||||
<template #default="{ row: scopeRow }">
|
<template #default="{ row: scopeRow }">
|
||||||
<span v-if="scopeRow.status === 2">手动填报</span>
|
<span v-if="scopeRow.finishType === '1'">手动填报</span>
|
||||||
<span v-if="scopeRow.status === 3">AI识别</span>
|
<span v-if="scopeRow.finishType === '2'">AI识别</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="操作" align="center" min-width="100px">
|
<el-table-column label="操作" align="center" min-width="100px">
|
||||||
<template #default="{ row: scopeRow }">
|
<template #default="{ row: scopeRow }">
|
||||||
<el-button type="danger" link @click="handleRemove(scopeRow)">
|
<el-button type="danger" link @click="handleRemove(scopeRow)">
|
||||||
<el-icon><ele-SemiSelect /></el-icon>移除
|
<el-icon><Minus /></el-icon>移除
|
||||||
</el-button>
|
</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
@ -175,7 +184,7 @@ import { workScheduleListQuery } from '@/api/progress/plan/types';
|
|||||||
|
|
||||||
// 响应式状态
|
// 响应式状态
|
||||||
const state = reactive<{
|
const state = reactive<{
|
||||||
expandRowKeys: number[];
|
expandRowKeys: string[];
|
||||||
loading: boolean;
|
loading: boolean;
|
||||||
isShowDialog: boolean;
|
isShowDialog: boolean;
|
||||||
queryParams: workScheduleListQuery;
|
queryParams: workScheduleListQuery;
|
||||||
@ -186,7 +195,7 @@ const state = reactive<{
|
|||||||
workId: string;
|
workId: string;
|
||||||
id: string;
|
id: string;
|
||||||
submitTime: string;
|
submitTime: string;
|
||||||
finishedNum: number;
|
finishedNumber: number;
|
||||||
};
|
};
|
||||||
detialList: any[];
|
detialList: any[];
|
||||||
detailTotal: number;
|
detailTotal: number;
|
||||||
@ -225,12 +234,12 @@ const state = reactive<{
|
|||||||
workId: '',
|
workId: '',
|
||||||
id: '',
|
id: '',
|
||||||
submitTime: '选择日期',
|
submitTime: '选择日期',
|
||||||
finishedNum: 0
|
finishedNumber: 0
|
||||||
},
|
},
|
||||||
detialList: [],
|
detialList: [],
|
||||||
detailTotal: 0,
|
detailTotal: 0,
|
||||||
detailQueryParams: {
|
detailQueryParams: {
|
||||||
pageSize: 20,
|
pageSize: 10,
|
||||||
pageNum: 1
|
pageNum: 1
|
||||||
},
|
},
|
||||||
loading1: false,
|
loading1: false,
|
||||||
@ -242,7 +251,7 @@ const state = reactive<{
|
|||||||
detialWordList: [],
|
detialWordList: [],
|
||||||
detailTotalWork: 0,
|
detailTotalWork: 0,
|
||||||
detailQueryParamsWork: {
|
detailQueryParamsWork: {
|
||||||
pageSize: 20,
|
pageSize: 10,
|
||||||
pageNum: 1
|
pageNum: 1
|
||||||
},
|
},
|
||||||
single: true,
|
single: true,
|
||||||
@ -318,15 +327,13 @@ const resetForm = (bool: boolean) => {
|
|||||||
const getPvModuleList = () => {
|
const getPvModuleList = () => {
|
||||||
loading1.value = true;
|
loading1.value = true;
|
||||||
pvModuleList({
|
pvModuleList({
|
||||||
workId: formDetail.value.workId,
|
id: formDetail.value.id,
|
||||||
...detailQueryParams.value,
|
...detailQueryParams.value
|
||||||
type: infoDetail.value.work_type,
|
|
||||||
status: 0
|
|
||||||
}).then((res: any) => {
|
}).then((res: any) => {
|
||||||
loading1.value = false;
|
loading1.value = false;
|
||||||
if (res.code === 0) {
|
if (res.code === 200) {
|
||||||
detialList.value = res.data.list;
|
detialList.value = res.rows;
|
||||||
detailTotal.value = res.data.total;
|
detailTotal.value = res.total;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -335,13 +342,13 @@ const getPvModuleList = () => {
|
|||||||
const getWorkList = (bool = false) => {
|
const getWorkList = (bool = false) => {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
workScheduleList(queryParams.value).then((res: any) => {
|
workScheduleList(queryParams.value).then((res: any) => {
|
||||||
if (res.code === 0) {
|
if (res.code === 200) {
|
||||||
state.tableData = res.data.list.map((item: any, i: number) => {
|
state.tableData = res.rows.map((item: any, i: number) => {
|
||||||
item.index = i + 1;
|
item.index = i + 1;
|
||||||
item.autoFill = item.detail?.reduce((sum: number, child: any) => sum + child.autoFill, 0) || 0;
|
item.aiFill = item.detailList?.reduce((sum: number, child: any) => sum + child.aiFill, 0) || 0;
|
||||||
return item;
|
return item;
|
||||||
});
|
});
|
||||||
state.total = res.data.total;
|
state.total = res.total;
|
||||||
}
|
}
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
});
|
});
|
||||||
@ -366,7 +373,7 @@ const indexMethod = (index: number): number => {
|
|||||||
// 日报添加
|
// 日报添加
|
||||||
const handleDayAdd = (row: any, obj: any) => {
|
const handleDayAdd = (row: any, obj: any) => {
|
||||||
resetForm(true);
|
resetForm(true);
|
||||||
formDetail.value.id = obj.id;
|
formDetail.value.id = row.id;
|
||||||
formDetail.value.submitTime = row.date;
|
formDetail.value.submitTime = row.date;
|
||||||
state.updateRow = row;
|
state.updateRow = row;
|
||||||
getPvModuleList();
|
getPvModuleList();
|
||||||
@ -376,8 +383,9 @@ const tableKey = (row: any) => row.id;
|
|||||||
|
|
||||||
// 展开行处理
|
// 展开行处理
|
||||||
const clickOpen = (row: any) => {
|
const clickOpen = (row: any) => {
|
||||||
const index = state.expandRowKeys.indexOf(row.id);
|
const rowId = String(row.id);
|
||||||
index === -1 ? state.expandRowKeys.push(row.id) : state.expandRowKeys.splice(index, 1);
|
const index = state.expandRowKeys.indexOf(rowId);
|
||||||
|
index === -1 ? state.expandRowKeys.push(rowId) : state.expandRowKeys.splice(index, 1);
|
||||||
state.expandRowKeys = [...new Set(state.expandRowKeys)];
|
state.expandRowKeys = [...new Set(state.expandRowKeys)];
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -394,22 +402,21 @@ const onUploadDaily = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const obj = {
|
const obj = {
|
||||||
ids: checkedList.value,
|
finishedDetailIdList: checkedList.value,
|
||||||
workID: formDetail.value.workId,
|
id: formDetail.value.id
|
||||||
doneTime: formDetail.value.submitTime,
|
|
||||||
planID: formDetail.value.id
|
|
||||||
};
|
};
|
||||||
|
|
||||||
state.flag = true;
|
state.flag = true;
|
||||||
addDaily(obj).then((res: any) => {
|
addDaily(obj).then((res: any) => {
|
||||||
if (res.code === 0) {
|
if (res.code === 200) {
|
||||||
ElMessage.success('添加成功');
|
ElMessage.success('添加成功');
|
||||||
if (state.updateRow) {
|
if (state.updateRow) {
|
||||||
state.updateRow.finishedNum += checkedList.value.length;
|
state.updateRow.finishedNumber += checkedList.value.length;
|
||||||
}
|
}
|
||||||
checkedList.value = [];
|
checkedList.value = [];
|
||||||
multipleTableRef.value?.clearSelection();
|
multipleTableRef.value?.clearSelection();
|
||||||
getPvModuleList();
|
getPvModuleList();
|
||||||
|
getWorkList();
|
||||||
} else {
|
} else {
|
||||||
ElMessage.error(res.message);
|
ElMessage.error(res.message);
|
||||||
}
|
}
|
||||||
@ -420,10 +427,11 @@ const onUploadDaily = () => {
|
|||||||
// 查看日报
|
// 查看日报
|
||||||
const handleView = (row: any, obj: any) => {
|
const handleView = (row: any, obj: any) => {
|
||||||
resetForm(false);
|
resetForm(false);
|
||||||
getDailyBookList(row.date);
|
|
||||||
state.updateRow = row;
|
state.updateRow = row;
|
||||||
formDetail.value.id = obj.id;
|
formDetail.value.id = row.id;
|
||||||
formDetail.value.submitTime = row.date;
|
formDetail.value.submitTime = row.date;
|
||||||
|
getDailyBookList(row.date);
|
||||||
|
|
||||||
showDayWork.value = false;
|
showDayWork.value = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -431,12 +439,12 @@ const handleView = (row: any, obj: any) => {
|
|||||||
const getDailyBookList = (doneTime: string) => {
|
const getDailyBookList = (doneTime: string) => {
|
||||||
detialWordList.value = [];
|
detialWordList.value = [];
|
||||||
getDailyBook({
|
getDailyBook({
|
||||||
workId: formDetail.value.workId,
|
id: formDetail.value.id,
|
||||||
type: infoDetail.value.work_type,
|
...detailQueryParams.value
|
||||||
doneTime
|
|
||||||
}).then((res: any) => {
|
}).then((res: any) => {
|
||||||
if (res.code === 0) {
|
if (res.code === 200) {
|
||||||
detialWordList.value = res.data.list || [];
|
detialWordList.value = res.rows || [];
|
||||||
|
detailTotalWork.value = res.total;
|
||||||
} else {
|
} else {
|
||||||
ElMessage.error(res.message);
|
ElMessage.error(res.message);
|
||||||
}
|
}
|
||||||
@ -453,10 +461,8 @@ const handleSelectionChangeWork = (selection: any[]) => {
|
|||||||
const handleRemove = (row?: any) => {
|
const handleRemove = (row?: any) => {
|
||||||
const planID = row ? [row.id] : state.checkList;
|
const planID = row ? [row.id] : state.checkList;
|
||||||
const obj = {
|
const obj = {
|
||||||
planID,
|
detailIdList: planID,
|
||||||
id: formDetail.value.id,
|
id: formDetail.value.id
|
||||||
workID: formDetail.value.workId,
|
|
||||||
time: formDetail.value.submitTime
|
|
||||||
};
|
};
|
||||||
|
|
||||||
ElMessageBox.confirm('确认移除该条数据?', '温馨提示', {
|
ElMessageBox.confirm('确认移除该条数据?', '温馨提示', {
|
||||||
@ -466,12 +472,13 @@ const handleRemove = (row?: any) => {
|
|||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
deleteDaily(obj).then((res: any) => {
|
deleteDaily(obj).then((res: any) => {
|
||||||
if (res.code === 0) {
|
if (res.code === 200) {
|
||||||
ElMessage.success('移除成功');
|
ElMessage.success('移除成功');
|
||||||
if (state.updateRow) {
|
if (state.updateRow) {
|
||||||
state.updateRow.finishedNum -= planID.length;
|
state.updateRow.finishedNumber -= planID.length;
|
||||||
}
|
}
|
||||||
getDailyBookList(formDetail.value.submitTime);
|
getDailyBookList(formDetail.value.submitTime);
|
||||||
|
getWorkList();
|
||||||
} else {
|
} else {
|
||||||
ElMessage.error(res.message);
|
ElMessage.error(res.message);
|
||||||
}
|
}
|
||||||
@ -482,14 +489,14 @@ const handleRemove = (row?: any) => {
|
|||||||
|
|
||||||
// 延期计算
|
// 延期计算
|
||||||
const filterW = (row: any): number => {
|
const filterW = (row: any): number => {
|
||||||
const { finishedNum, planNum, endAt } = row;
|
const { finishedNumber, planNumber, endAt } = row;
|
||||||
if (!endAt) return 0;
|
if (!endAt) return 0;
|
||||||
|
|
||||||
const endTime = new Date(endAt).getTime();
|
const endTime = new Date(endAt).getTime();
|
||||||
const now = new Date().getTime();
|
const now = new Date().getTime();
|
||||||
|
|
||||||
if (endTime <= now && planNum > finishedNum) {
|
if (endTime <= now && planNumber > finishedNumber) {
|
||||||
return planNum - finishedNum;
|
return planNumber - finishedNumber;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
@ -500,6 +507,32 @@ defineExpose({
|
|||||||
closeDialog
|
closeDialog
|
||||||
});
|
});
|
||||||
const emit = defineEmits(['getProgressList']);
|
const emit = defineEmits(['getProgressList']);
|
||||||
|
|
||||||
|
let scrollTop = 0;
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => isShowDialog.value,
|
||||||
|
(visible) => {
|
||||||
|
if (visible) {
|
||||||
|
scrollTop = window.scrollY || document.documentElement.scrollTop;
|
||||||
|
const scrollbarWidth = window.innerWidth - document.documentElement.clientWidth;
|
||||||
|
|
||||||
|
document.body.style.position = 'fixed';
|
||||||
|
document.body.style.top = `-${scrollTop}px`;
|
||||||
|
document.body.style.width = '100%';
|
||||||
|
document.body.style.paddingRight = `${scrollbarWidth}px`; // 👈 补偿滚动条宽度
|
||||||
|
} else {
|
||||||
|
document.body.style.position = '';
|
||||||
|
document.body.style.top = '';
|
||||||
|
document.body.style.width = '';
|
||||||
|
document.body.style.paddingRight = ''; // 👈 恢复
|
||||||
|
|
||||||
|
nextTick(() => {
|
||||||
|
window.scrollTo(0, scrollTop);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
@ -253,6 +253,7 @@ const onSubmit = () => {
|
|||||||
workScheduleAddPlan(payload).then((res: any) => {
|
workScheduleAddPlan(payload).then((res: any) => {
|
||||||
if (res.code === 200) {
|
if (res.code === 200) {
|
||||||
ElMessage.success('添加成功');
|
ElMessage.success('添加成功');
|
||||||
|
emit('getProgressList');
|
||||||
closeDialog();
|
closeDialog();
|
||||||
} else {
|
} else {
|
||||||
ElMessage.error(res.message);
|
ElMessage.error(res.message);
|
||||||
@ -292,6 +293,7 @@ const fetchLastTime = (row: typeof infoDetail) => {
|
|||||||
|
|
||||||
// Export function if needed externally
|
// Export function if needed externally
|
||||||
defineExpose({ openDialog });
|
defineExpose({ openDialog });
|
||||||
|
const emit = defineEmits(['getProgressList']);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
|
@ -47,10 +47,27 @@
|
|||||||
border
|
border
|
||||||
>
|
>
|
||||||
<el-table-column label="" width="50" type="expand">
|
<el-table-column label="" width="50" type="expand">
|
||||||
|
<template #header>
|
||||||
|
<el-icon
|
||||||
|
class="cursor-pointer text-4! transform-rotate-z--90 transition-all-300"
|
||||||
|
:class="!isExpandAll ? 'transform-rotate-z--90' : 'transform-rotate-z-90'"
|
||||||
|
@click="handleToggleExpandAll"
|
||||||
|
><Expand
|
||||||
|
/></el-icon>
|
||||||
|
</template>
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-card class="pl-25" shadow="hover">
|
<el-card class="pl-25" shadow="hover">
|
||||||
<el-table :data="scope.row.children" border>
|
<el-table :data="scope.row.children" border>
|
||||||
<el-table-column label="名称" align="center" prop="name" width="150" />
|
<el-table-column label="名称" align="center" prop="name" width="170">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<el-tooltip :content="row.remark" placement="top" effect="dark" v-if="row.remark">
|
||||||
|
<span class="flex items-center justify-center"
|
||||||
|
><i class="iconfont icon-wenhao mr-0.5 text-3.5! text-#999"></i>{{ row.name }}</span
|
||||||
|
>
|
||||||
|
</el-tooltip>
|
||||||
|
<span v-else>{{ row.name }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
<el-table-column label="状态" align="center" prop="status" width="100">
|
<el-table-column label="状态" align="center" prop="status" width="100">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<dict-tag :options="progress_status" :value="row.status" />
|
<dict-tag :options="progress_status" :value="row.status" />
|
||||||
@ -85,7 +102,7 @@
|
|||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="200">
|
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="200">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-button
|
<!-- <el-button
|
||||||
type="warning"
|
type="warning"
|
||||||
icon="Download"
|
icon="Download"
|
||||||
link
|
link
|
||||||
@ -94,12 +111,13 @@
|
|||||||
v-hasPermi="['progress:progressCategory:add']"
|
v-hasPermi="['progress:progressCategory:add']"
|
||||||
>
|
>
|
||||||
导入数据
|
导入数据
|
||||||
</el-button>
|
</el-button> -->
|
||||||
<el-button
|
<el-button
|
||||||
type="warning"
|
type="warning"
|
||||||
icon="Download"
|
icon="Download"
|
||||||
link
|
link
|
||||||
size="small"
|
size="small"
|
||||||
|
v-if="scope.row.name === '光伏板'"
|
||||||
@click="openDialog(scope.row, 'importTableStatus', '上传表格')"
|
@click="openDialog(scope.row, 'importTableStatus', '上传表格')"
|
||||||
v-hasPermi="['progress:progressCategory:add']"
|
v-hasPermi="['progress:progressCategory:add']"
|
||||||
>
|
>
|
||||||
@ -254,10 +272,14 @@ const { queryParams, form, rules } = toRefs(data);
|
|||||||
const getList = async () => {
|
const getList = async () => {
|
||||||
if (!queryParams.value.matrixId) {
|
if (!queryParams.value.matrixId) {
|
||||||
const res = await getProjectSquare(currentProject.value.id);
|
const res = await getProjectSquare(currentProject.value.id);
|
||||||
|
if (res.rows.length === 0) {
|
||||||
|
proxy?.$modal.msgWarning('当前项目下没有方阵,请先创建方阵');
|
||||||
|
} else {
|
||||||
if (!matrixValue.value) matrixValue.value = res.rows[0].id;
|
if (!matrixValue.value) matrixValue.value = res.rows[0].id;
|
||||||
matrixOptions.value = res.rows;
|
matrixOptions.value = res.rows;
|
||||||
queryParams.value.matrixId = res.rows[0].id;
|
queryParams.value.matrixId = res.rows[0].id;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
const res = await listProgressCategory(queryParams.value);
|
const res = await listProgressCategory(queryParams.value);
|
||||||
const data = proxy?.handleTree<ProgressCategoryVO>(res.data, 'id', 'pid');
|
const data = proxy?.handleTree<ProgressCategoryVO>(res.data, 'id', 'pid');
|
||||||
@ -288,6 +310,13 @@ const reset = () => {
|
|||||||
progressCategoryFormRef.value?.resetFields();
|
progressCategoryFormRef.value?.resetFields();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//切换项目重置方阵
|
||||||
|
const resetMatrix = () => {
|
||||||
|
matrixValue.value = undefined;
|
||||||
|
queryParams.value.matrixId = undefined;
|
||||||
|
matrixOptions.value = [];
|
||||||
|
};
|
||||||
|
|
||||||
/** 搜索按钮操作 */
|
/** 搜索按钮操作 */
|
||||||
const handleQuery = () => {
|
const handleQuery = () => {
|
||||||
getList();
|
getList();
|
||||||
@ -384,6 +413,7 @@ const listeningProject = watch(
|
|||||||
(nid, oid) => {
|
(nid, oid) => {
|
||||||
queryParams.value.projectId = nid;
|
queryParams.value.projectId = nid;
|
||||||
form.value.projectId = nid;
|
form.value.projectId = nid;
|
||||||
|
resetMatrix();
|
||||||
getList();
|
getList();
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
282
src/views/progress/progressCategoryTemplate/index.vue
Normal file
282
src/views/progress/progressCategoryTemplate/index.vue
Normal file
@ -0,0 +1,282 @@
|
|||||||
|
<template>
|
||||||
|
<div class="p-2">
|
||||||
|
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
||||||
|
<div v-show="showSearch" class="mb-[10px]">
|
||||||
|
<el-card shadow="hover">
|
||||||
|
<el-form ref="queryFormRef" :model="queryParams" :inline="true">
|
||||||
|
<el-form-item label="父类别id" prop="pid">
|
||||||
|
<el-input v-model="queryParams.pid" placeholder="请输入父类别id" clearable @keyup.enter="handleQuery" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="类别名称" prop="name">
|
||||||
|
<el-input v-model="queryParams.name" placeholder="请输入类别名称" clearable @keyup.enter="handleQuery" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="项目id" prop="projectId">
|
||||||
|
<el-input v-model="queryParams.projectId" placeholder="请输入项目id" clearable @keyup.enter="handleQuery" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
|
||||||
|
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</el-card>
|
||||||
|
</div>
|
||||||
|
</transition>
|
||||||
|
|
||||||
|
<el-card shadow="never">
|
||||||
|
<template #header>
|
||||||
|
<el-row :gutter="10" class="mb8">
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button type="primary" plain icon="Plus" @click="handleAdd()" v-hasPermi="['progress:progressCategoryTemplate:add']">新增</el-button>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button type="info" plain icon="Sort" @click="handleToggleExpandAll">展开/折叠</el-button>
|
||||||
|
</el-col>
|
||||||
|
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
|
||||||
|
</el-row>
|
||||||
|
</template>
|
||||||
|
<el-table
|
||||||
|
ref="progressCategoryTemplateTableRef"
|
||||||
|
v-loading="loading"
|
||||||
|
:data="progressCategoryTemplateList"
|
||||||
|
row-key="id"
|
||||||
|
:default-expand-all="isExpandAll"
|
||||||
|
:tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
|
||||||
|
>
|
||||||
|
<el-table-column label="类别名称" align="center" prop="name" />
|
||||||
|
<el-table-column label="计量方式" align="center" prop="unitType" />
|
||||||
|
<el-table-column label="工作类型" align="center" prop="workType" />
|
||||||
|
<el-table-column label="项目id" align="center" prop="projectId" />
|
||||||
|
<el-table-column label="备注" align="center" prop="remark" />
|
||||||
|
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-tooltip content="修改" placement="top">
|
||||||
|
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['progress:progressCategoryTemplate:edit']" />
|
||||||
|
</el-tooltip>
|
||||||
|
<el-tooltip content="新增" placement="top">
|
||||||
|
<el-button link type="primary" icon="Plus" @click="handleAdd(scope.row)" v-hasPermi="['progress:progressCategoryTemplate:add']" />
|
||||||
|
</el-tooltip>
|
||||||
|
<el-tooltip content="删除" placement="top">
|
||||||
|
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['progress:progressCategoryTemplate:remove']" />
|
||||||
|
</el-tooltip>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</el-card>
|
||||||
|
<!-- 添加或修改进度类别模版对话框 -->
|
||||||
|
<el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
|
||||||
|
<el-form ref="progressCategoryTemplateFormRef" :model="form" :rules="rules" label-width="80px">
|
||||||
|
<el-form-item label="父类别id" prop="pid">
|
||||||
|
<el-tree-select
|
||||||
|
v-model="form.pid"
|
||||||
|
:data="progressCategoryTemplateOptions"
|
||||||
|
:props="{ value: 'id', label: 'name', children: 'children' }"
|
||||||
|
value-key="id"
|
||||||
|
placeholder="请选择父类别id"
|
||||||
|
check-strictly
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="类别名称" prop="name">
|
||||||
|
<el-input v-model="form.name" placeholder="请输入类别名称" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="项目id" prop="projectId">
|
||||||
|
<el-input v-model="form.projectId" placeholder="请输入项目id" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="备注" prop="remark">
|
||||||
|
<el-input v-model="form.remark" type="textarea" placeholder="请输入内容" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<div class="dialog-footer">
|
||||||
|
<el-button :loading="buttonLoading" type="primary" @click="submitForm">确 定</el-button>
|
||||||
|
<el-button @click="cancel">取 消</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup name="ProgressCategoryTemplate" lang="ts">
|
||||||
|
import { listProgressCategoryTemplate, getProgressCategoryTemplate, delProgressCategoryTemplate, addProgressCategoryTemplate, updateProgressCategoryTemplate } from "@/api/progress/progressCategoryTemplate";
|
||||||
|
import { ProgressCategoryTemplateVO, ProgressCategoryTemplateQuery, ProgressCategoryTemplateForm } from '@/api/progress/progressCategoryTemplate/types';
|
||||||
|
|
||||||
|
type ProgressCategoryTemplateOption = {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
children?: ProgressCategoryTemplateOption[];
|
||||||
|
}
|
||||||
|
|
||||||
|
const { proxy } = getCurrentInstance() as ComponentInternalInstance;;
|
||||||
|
|
||||||
|
|
||||||
|
const progressCategoryTemplateList = ref<ProgressCategoryTemplateVO[]>([]);
|
||||||
|
const progressCategoryTemplateOptions = ref<ProgressCategoryTemplateOption[]>([]);
|
||||||
|
const buttonLoading = ref(false);
|
||||||
|
const showSearch = ref(true);
|
||||||
|
const isExpandAll = ref(true);
|
||||||
|
const loading = ref(false);
|
||||||
|
|
||||||
|
const queryFormRef = ref<ElFormInstance>();
|
||||||
|
const progressCategoryTemplateFormRef = ref<ElFormInstance>();
|
||||||
|
const progressCategoryTemplateTableRef = ref<ElTableInstance>()
|
||||||
|
|
||||||
|
const dialog = reactive<DialogOption>({
|
||||||
|
visible: false,
|
||||||
|
title: ''
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
const initFormData: ProgressCategoryTemplateForm = {
|
||||||
|
id: undefined,
|
||||||
|
pid: undefined,
|
||||||
|
name: undefined,
|
||||||
|
unitType: undefined,
|
||||||
|
workType: undefined,
|
||||||
|
projectId: undefined,
|
||||||
|
remark: undefined,
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = reactive<PageData<ProgressCategoryTemplateForm, ProgressCategoryTemplateQuery>>({
|
||||||
|
form: {...initFormData},
|
||||||
|
queryParams: {
|
||||||
|
pid: undefined,
|
||||||
|
name: undefined,
|
||||||
|
unitType: undefined,
|
||||||
|
workType: undefined,
|
||||||
|
projectId: undefined,
|
||||||
|
params: {
|
||||||
|
}
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
id: [
|
||||||
|
{ required: true, message: "主键id不能为空", trigger: "blur" }
|
||||||
|
],
|
||||||
|
pid: [
|
||||||
|
{ required: true, message: "父类别id不能为空", trigger: "blur" }
|
||||||
|
],
|
||||||
|
name: [
|
||||||
|
{ required: true, message: "类别名称不能为空", trigger: "blur" }
|
||||||
|
],
|
||||||
|
unitType: [
|
||||||
|
{ required: true, message: "计量方式不能为空", trigger: "change" }
|
||||||
|
],
|
||||||
|
projectId: [
|
||||||
|
{ required: true, message: "项目id不能为空", trigger: "blur" }
|
||||||
|
],
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const { queryParams, form, rules } = toRefs(data);
|
||||||
|
|
||||||
|
/** 查询进度类别模版列表 */
|
||||||
|
const getList = async () => {
|
||||||
|
loading.value = true;
|
||||||
|
const res = await listProgressCategoryTemplate(queryParams.value);
|
||||||
|
const data = proxy?.handleTree<ProgressCategoryTemplateVO>(res.data, "id", "pid");
|
||||||
|
if (data) {
|
||||||
|
progressCategoryTemplateList.value = data;
|
||||||
|
loading.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询进度类别模版下拉树结构 */
|
||||||
|
const getTreeselect = async () => {
|
||||||
|
const res = await listProgressCategoryTemplate();
|
||||||
|
progressCategoryTemplateOptions.value = [];
|
||||||
|
const data: ProgressCategoryTemplateOption = { id: 0, name: '顶级节点', children: [] };
|
||||||
|
data.children = proxy?.handleTree<ProgressCategoryTemplateOption>(res.data, "id", "pid");
|
||||||
|
progressCategoryTemplateOptions.value.push(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 取消按钮
|
||||||
|
const cancel = () => {
|
||||||
|
reset();
|
||||||
|
dialog.visible = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 表单重置
|
||||||
|
const reset = () => {
|
||||||
|
form.value = {...initFormData}
|
||||||
|
progressCategoryTemplateFormRef.value?.resetFields();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 搜索按钮操作 */
|
||||||
|
const handleQuery = () => {
|
||||||
|
getList();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 重置按钮操作 */
|
||||||
|
const resetQuery = () => {
|
||||||
|
queryFormRef.value?.resetFields();
|
||||||
|
handleQuery();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 新增按钮操作 */
|
||||||
|
const handleAdd = (row?: ProgressCategoryTemplateVO) => {
|
||||||
|
reset();
|
||||||
|
getTreeselect();
|
||||||
|
if (row != null && row.id) {
|
||||||
|
form.value.pid = row.id;
|
||||||
|
} else {
|
||||||
|
form.value.pid = 0;
|
||||||
|
}
|
||||||
|
dialog.visible = true;
|
||||||
|
dialog.title = "添加进度类别模版";
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 展开/折叠操作 */
|
||||||
|
const handleToggleExpandAll = () => {
|
||||||
|
isExpandAll.value = !isExpandAll.value;
|
||||||
|
toggleExpandAll(progressCategoryTemplateList.value, isExpandAll.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 展开/折叠操作 */
|
||||||
|
const toggleExpandAll = (data: ProgressCategoryTemplateVO[], status: boolean) => {
|
||||||
|
data.forEach((item) => {
|
||||||
|
progressCategoryTemplateTableRef.value?.toggleRowExpansion(item, status)
|
||||||
|
if (item.children && item.children.length > 0) toggleExpandAll(item.children, status)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 修改按钮操作 */
|
||||||
|
const handleUpdate = async (row: ProgressCategoryTemplateVO) => {
|
||||||
|
reset();
|
||||||
|
await getTreeselect();
|
||||||
|
if (row != null) {
|
||||||
|
form.value.pid = row.pid;
|
||||||
|
}
|
||||||
|
const res = await getProgressCategoryTemplate(row.id);
|
||||||
|
Object.assign(form.value, res.data);
|
||||||
|
dialog.visible = true;
|
||||||
|
dialog.title = "修改进度类别模版";
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 提交按钮 */
|
||||||
|
const submitForm = () => {
|
||||||
|
progressCategoryTemplateFormRef.value?.validate(async (valid: boolean) => {
|
||||||
|
if (valid) {
|
||||||
|
buttonLoading.value = true;
|
||||||
|
if (form.value.id) {
|
||||||
|
await updateProgressCategoryTemplate(form.value).finally(() => buttonLoading.value = false);
|
||||||
|
} else {
|
||||||
|
await addProgressCategoryTemplate(form.value).finally(() => buttonLoading.value = false);
|
||||||
|
}
|
||||||
|
proxy?.$modal.msgSuccess("操作成功");
|
||||||
|
dialog.visible = false;
|
||||||
|
getList();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 删除按钮操作 */
|
||||||
|
const handleDelete = async (row: ProgressCategoryTemplateVO) => {
|
||||||
|
await proxy?.$modal.confirm('是否确认删除进度类别模版编号为"' + row.id + '"的数据项?');
|
||||||
|
loading.value = true;
|
||||||
|
await delProgressCategoryTemplate(row.id).finally(() => loading.value = false);
|
||||||
|
await getList();
|
||||||
|
proxy?.$modal.msgSuccess("删除成功");
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
getList();
|
||||||
|
});
|
||||||
|
</script>
|
479
src/views/progress/progressPaper/index.vue
Normal file
479
src/views/progress/progressPaper/index.vue
Normal file
@ -0,0 +1,479 @@
|
|||||||
|
<template>
|
||||||
|
<div class="header flex justify-end">
|
||||||
|
<el-form :model="queryParams" ref="form" label-width="80px" inline class="flex items-center">
|
||||||
|
<el-form-item label="请选择项目:" prop="pid" label-width="100">
|
||||||
|
<el-select v-model="selectedProjectId" placeholder="请选择" @change="handleSelect" clearable>
|
||||||
|
<el-option v-for="item in ProjectList" :key="item.id" :label="item.name" :value="item.id" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="请选择方阵:" prop="pid" label-width="100">
|
||||||
|
<el-select v-model="matrixValue" placeholder="请选择" @change="handleChange" clearable>
|
||||||
|
<el-option v-for="item in matrixOptions" :key="item.id" :label="item.matrixName" :value="item.id" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</div>
|
||||||
|
<div class="ol-map" id="olMap"></div>
|
||||||
|
<div class="aside">
|
||||||
|
<el-tree
|
||||||
|
style="max-width: 600px"
|
||||||
|
:data="progressCategoryList"
|
||||||
|
ref="treeRef"
|
||||||
|
show-checkbox
|
||||||
|
@check-change="handleCheckChange"
|
||||||
|
:props="treeProps"
|
||||||
|
:load="loadNode"
|
||||||
|
node-key="id"
|
||||||
|
lazy
|
||||||
|
@node-collapse="closeNode"
|
||||||
|
@node-expand="openNode"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="submit">
|
||||||
|
<el-button type="primary" size="default" @click="submit">提交</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import Map from 'ol/Map'; // OpenLayers的主要类,用于创建和管理地图
|
||||||
|
import View from 'ol/View'; // OpenLayers的视图类,定义地图的视图属性
|
||||||
|
import { Tile as TileLayer } from 'ol/layer'; // OpenLayers的瓦片图层类
|
||||||
|
import { XYZ } from 'ol/source'; // OpenLayers的瓦片数据源,包括XYZ格式和OpenStreetMap专用的数据源
|
||||||
|
import { defaults as defaultControls, defaults, FullScreen, MousePosition, ScaleLine } from 'ol/control';
|
||||||
|
import { fromLonLat } from 'ol/proj';
|
||||||
|
import { useUserStoreHook } from '@/store/modules/user';
|
||||||
|
import { getProjectSquare, listProgressCategory, addDaily, workScheduleListPosition } from '@/api/progress/plan';
|
||||||
|
import { ProgressCategoryVO, progressPlanDetailForm } from '@/api/progress/plan/types';
|
||||||
|
import { Circle, Fill, Stroke, Style, Text } from 'ol/style';
|
||||||
|
import Feature from 'ol/Feature';
|
||||||
|
import { Point, Polygon } from 'ol/geom';
|
||||||
|
import VectorSource from 'ol/source/Vector';
|
||||||
|
import VectorLayer from 'ol/layer/Vector';
|
||||||
|
import Node from 'element-plus/es/components/tree/src/model/node.mjs';
|
||||||
|
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||||
|
|
||||||
|
// 获取用户 store
|
||||||
|
const userStore = useUserStoreHook();
|
||||||
|
// 从 store 中获取项目列表和当前选中的项目
|
||||||
|
const currentProject = computed(() => userStore.selectedProject);
|
||||||
|
const ProjectList = computed(() => userStore.projects);
|
||||||
|
const selectedProjectId = ref(userStore.selectedProject?.id || '');
|
||||||
|
const treeRef = ref();
|
||||||
|
const queryParams = ref({
|
||||||
|
pid: undefined,
|
||||||
|
name: undefined,
|
||||||
|
unitType: undefined,
|
||||||
|
projectId: currentProject.value.id,
|
||||||
|
matrixId: undefined,
|
||||||
|
params: {}
|
||||||
|
});
|
||||||
|
const submitForm = ref<progressPlanDetailForm>({
|
||||||
|
id: '',
|
||||||
|
finishedDetailIdList: [] as string[]
|
||||||
|
});
|
||||||
|
const loading = ref(false);
|
||||||
|
const matrixOptions = ref([]);
|
||||||
|
const matrixValue = ref<number | undefined>(matrixOptions.value.length > 0 ? matrixOptions.value[0].id : undefined);
|
||||||
|
const progressCategoryList = ref<ProgressCategoryVO[]>([]);
|
||||||
|
const treeProps = {
|
||||||
|
children: 'children',
|
||||||
|
label: 'name',
|
||||||
|
isLeaf: 'leaf',
|
||||||
|
hasChildren: 'hasChildren' // 重要
|
||||||
|
};
|
||||||
|
|
||||||
|
//切换项目
|
||||||
|
const handleSelect = (projectId: string) => {
|
||||||
|
const selectedProject = ProjectList.value.find((p) => p.id === projectId);
|
||||||
|
if (selectedProject) {
|
||||||
|
userStore.setSelectedProject(selectedProject);
|
||||||
|
|
||||||
|
resetMatrix();
|
||||||
|
getList();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 进度类别树选中事件 */
|
||||||
|
const handleCheckChange = (data: any, checked: boolean, indeterminate: boolean) => {
|
||||||
|
const node: Node | undefined = treeRef.value?.getNode(data.id);
|
||||||
|
if (node && node.level === 3) {
|
||||||
|
console.log('第三级节点被选中:', data, '选中状态:', checked);
|
||||||
|
}
|
||||||
|
if (!node || node.level !== 3 || !checked) return;
|
||||||
|
|
||||||
|
const parent = node.parent;
|
||||||
|
if (!parent) return;
|
||||||
|
|
||||||
|
// 遍历兄弟节点,取消选中除当前节点之外的其他第三级节点
|
||||||
|
parent.childNodes.forEach((sibling: Node) => {
|
||||||
|
if (sibling !== node) {
|
||||||
|
treeRef.value.setChecked(sibling.data.id, false, false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
submitForm.value.id = data.id; // 设置提交表单的id
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 关闭节点事件 */
|
||||||
|
const closeNode = (node: any) => {
|
||||||
|
// 清除子节点
|
||||||
|
if (node.pid) {
|
||||||
|
node.threeChildren.forEach((child: any) => {
|
||||||
|
const feature = featureMap[child.id];
|
||||||
|
if (feature && sharedSource.hasFeature(feature)) {
|
||||||
|
sharedSource.removeFeature(feature);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 打开节点事件 */
|
||||||
|
const openNode = (node: any) => {
|
||||||
|
// 清除子节点
|
||||||
|
if (!node.pid) return;
|
||||||
|
addPointToMap(node.threeChildren); // 添加点到地图
|
||||||
|
};
|
||||||
|
|
||||||
|
//懒加载子节点
|
||||||
|
const loadNode = async (node: any, resolve: (data: any[]) => void) => {
|
||||||
|
if (node.level !== 2) {
|
||||||
|
// 只对二级节点加载子节点
|
||||||
|
resolve(node.data.children || []);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const secondLevelNodeId = node.data.id;
|
||||||
|
const res = await workScheduleListPosition(secondLevelNodeId); // 替换成你的 API
|
||||||
|
|
||||||
|
const children = res.data.detailList || [];
|
||||||
|
|
||||||
|
if (children.length === 0) {
|
||||||
|
proxy?.$modal.msgWarning(`节点 "${node.data.name}" 为空`);
|
||||||
|
resolve([]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 标记子节点为叶子节点
|
||||||
|
const threeLeafList = children.map((detail) => {
|
||||||
|
return {
|
||||||
|
...detail,
|
||||||
|
name: detail.date, // 设置为叶子节点
|
||||||
|
leaf: true // 标记为叶子节点
|
||||||
|
};
|
||||||
|
});
|
||||||
|
progressCategoryList.value.forEach((item, i) => {
|
||||||
|
let indexNum = item.children.findIndex((item) => item.id === secondLevelNodeId);
|
||||||
|
if (indexNum !== -1) {
|
||||||
|
item.children[indexNum].threeChildren = res.data.facilityList; // 将子节点添加到当前节点的threeChildren属性中
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
resolve(threeLeafList);
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 提交按钮点击事件 */
|
||||||
|
const submit = () => {
|
||||||
|
console.log('sunbmitForm', submitForm.value);
|
||||||
|
addDaily(submitForm.value)
|
||||||
|
.then(() => {
|
||||||
|
proxy?.$modal.msgSuccess('提交成功');
|
||||||
|
resetTreeAndMap();
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
proxy?.$modal.msgError(`提交失败: ${error.message}`);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
//重置树形结构选中以及图层高亮
|
||||||
|
const resetTreeAndMap = () => {
|
||||||
|
// 重置树形结构选中状态
|
||||||
|
treeRef.value?.setCheckedKeys([]);
|
||||||
|
// 清除地图上的所有高亮
|
||||||
|
const scale = Math.max(map.getView().getZoom() / 10, 1); // 获取当前缩放比例
|
||||||
|
sharedSource.getFeatures().forEach((feature) => {
|
||||||
|
if (feature.get('highlighted')) {
|
||||||
|
feature.setStyle(defaultStyle(feature.get('name'), scale)); // 恢复默认样式
|
||||||
|
feature.set('highlighted', false); // 重置高亮状态
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// 清空已完成列表
|
||||||
|
submitForm.value.finishedDetailIdList = [];
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 方阵选择器改变事件 */
|
||||||
|
const handleChange = (value: number) => {
|
||||||
|
queryParams.value.matrixId = value;
|
||||||
|
|
||||||
|
getList();
|
||||||
|
};
|
||||||
|
|
||||||
|
//切换项目重置方阵
|
||||||
|
const resetMatrix = () => {
|
||||||
|
matrixValue.value = undefined;
|
||||||
|
queryParams.value.matrixId = undefined;
|
||||||
|
matrixOptions.value = [];
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 查询进度类别列表 */
|
||||||
|
const getList = async () => {
|
||||||
|
if (!queryParams.value.matrixId) {
|
||||||
|
const res = await getProjectSquare(currentProject.value.id);
|
||||||
|
if (res.rows.length === 0) {
|
||||||
|
proxy?.$modal.msgWarning('当前项目下没有方阵,请先创建方阵');
|
||||||
|
} else {
|
||||||
|
if (!matrixValue.value) matrixValue.value = res.rows[0].id;
|
||||||
|
matrixOptions.value = res.rows;
|
||||||
|
queryParams.value.matrixId = res.rows[0].id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
loading.value = true;
|
||||||
|
queryParams.value.projectId = currentProject.value.id;
|
||||||
|
const res = await listProgressCategory(queryParams.value);
|
||||||
|
const data = proxy?.handleTree<ProgressCategoryVO>(res.data, 'id', 'pid');
|
||||||
|
if (data) {
|
||||||
|
progressCategoryList.value = data;
|
||||||
|
loading.value = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let map: any = null;
|
||||||
|
const layerData = reactive<any>({});
|
||||||
|
const centerPosition = ref(fromLonLat([107.12932403398425, 23.805564054229908]));
|
||||||
|
|
||||||
|
const initOLMap = () => {
|
||||||
|
// 创造地图实例
|
||||||
|
map = new Map({
|
||||||
|
// 设置地图容器的ID
|
||||||
|
target: 'olMap',
|
||||||
|
// 定义地图的图层列表,用于显示特定的地理信息。
|
||||||
|
layers: [
|
||||||
|
// 高德地图
|
||||||
|
// TileLayer表示一个瓦片图层,它由一系列瓦片(通常是图片)组成,用于在地图上显示地理数据。
|
||||||
|
new TileLayer({
|
||||||
|
// 设置图层的数据源为XYZ类型。XYZ是一个通用的瓦片图层源,它允许你通过URL模板来获取瓦片
|
||||||
|
source: new XYZ({
|
||||||
|
url: 'https://webrd04.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=7&x={x}&y={y}&z={z}'
|
||||||
|
})
|
||||||
|
})
|
||||||
|
],
|
||||||
|
// 设置地图的视图参数
|
||||||
|
// View表示地图的视图,它定义了地图的中心点、缩放级别、旋转角度等参数。
|
||||||
|
view: new View({
|
||||||
|
// fromLonLat是一个函数,用于将经纬度坐标转换为地图的坐标系统。
|
||||||
|
center: centerPosition.value, //地图中心点
|
||||||
|
zoom: 15, // 缩放级别
|
||||||
|
minZoom: 0, // 最小缩放级别
|
||||||
|
// maxZoom: 18, // 最大缩放级别
|
||||||
|
constrainResolution: true // 因为存在非整数的缩放级别,所以设置该参数为true来让每次缩放结束后自动缩放到距离最近的一个整数级别,这个必须要设置,当缩放在非整数级别时地图会糊
|
||||||
|
// projection: 'EPSG:4326' // 投影坐标系,默认是3857
|
||||||
|
}),
|
||||||
|
|
||||||
|
//加载控件到地图容器中
|
||||||
|
controls: defaultControls({
|
||||||
|
zoom: false,
|
||||||
|
rotate: false,
|
||||||
|
attribution: false
|
||||||
|
})
|
||||||
|
});
|
||||||
|
map.on('click', (e: any) => {
|
||||||
|
const zoom = map.getView().getZoom();
|
||||||
|
const scale = Math.max(zoom / 10, 1); // 缩放比例,根据需要调整公式
|
||||||
|
map.forEachFeatureAtPixel(e.pixel, (feature: Feature) => {
|
||||||
|
if (feature.get('status') === '2') return; // 如果是完成状态,直接返回
|
||||||
|
const isHighlighted = feature.get('highlighted') === true;
|
||||||
|
const geomType = feature.getGeometry().getType();
|
||||||
|
if (isHighlighted) {
|
||||||
|
feature.setStyle(defaultStyle(feature.get('name'), scale)); // 清除高亮样式
|
||||||
|
feature.set('highlighted', false);
|
||||||
|
submitForm.value.finishedDetailIdList = submitForm.value.finishedDetailIdList.filter((id) => id !== feature.get('id')); // 从已完成列表中移除
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (geomType === 'Polygon') {
|
||||||
|
feature.setStyle(highlightStyle(feature.get('name'), scale));
|
||||||
|
feature.set('highlighted', true);
|
||||||
|
submitForm.value.finishedDetailIdList.push(feature.get('id')); // 添加到已完成列表
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
map.getView().on('change:resolution', () => {
|
||||||
|
const zoom = map.getView().getZoom();
|
||||||
|
const scale = Math.max(zoom / 10, 1); // 缩放比例,根据需要调整公式
|
||||||
|
|
||||||
|
sharedSource.getFeatures().forEach((feature) => {
|
||||||
|
const style = feature.getStyle();
|
||||||
|
|
||||||
|
if (style instanceof Style && style.getText()) {
|
||||||
|
style.getText().setScale(scale);
|
||||||
|
feature.setStyle(style); // 重新应用样式
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const highlightStyle = (name, scale) => {
|
||||||
|
return new Style({
|
||||||
|
stroke: new Stroke({
|
||||||
|
color: 'orange',
|
||||||
|
width: 4
|
||||||
|
}),
|
||||||
|
fill: new Fill({
|
||||||
|
color: 'rgba(255,165,0,0.3)' // 半透明橙色
|
||||||
|
}),
|
||||||
|
text: new Text({
|
||||||
|
font: '14px Microsoft YaHei',
|
||||||
|
text: name,
|
||||||
|
placement: 'line', // 👈 关键属性
|
||||||
|
offsetX: 50, // 向右偏移 10 像素
|
||||||
|
offsetY: 20, // 向下偏移 5 像素
|
||||||
|
scale,
|
||||||
|
fill: new Fill({ color: 'orange' })
|
||||||
|
})
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const defaultStyle = (name, scale) => {
|
||||||
|
return new Style({
|
||||||
|
stroke: new Stroke({
|
||||||
|
color: '#003366',
|
||||||
|
width: 2
|
||||||
|
}),
|
||||||
|
text: new Text({
|
||||||
|
font: '12px Microsoft YaHei',
|
||||||
|
text: name,
|
||||||
|
scale,
|
||||||
|
placement: 'line', // 👈 关键属性
|
||||||
|
offsetX: 50, // 向右偏移 10 像素
|
||||||
|
offsetY: 20, // 向下偏移 5 像素
|
||||||
|
fill: new Fill({ color: '#003366 ' })
|
||||||
|
}),
|
||||||
|
fill: new Fill({ color: 'skyblue' })
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const successStyle = (name, scale) => {
|
||||||
|
return new Style({
|
||||||
|
stroke: new Stroke({
|
||||||
|
color: '#2E7D32 ',
|
||||||
|
width: 2
|
||||||
|
}),
|
||||||
|
text: new Text({
|
||||||
|
font: '14px Microsoft YaHei',
|
||||||
|
text: name,
|
||||||
|
scale,
|
||||||
|
placement: 'line', // 👈 关键属性
|
||||||
|
offsetX: 50, // 向右偏移 10 像素
|
||||||
|
offsetY: 20, // 向下偏移 5 像素
|
||||||
|
fill: new Fill({ color: '#FFFFFF ' })
|
||||||
|
}),
|
||||||
|
fill: new Fill({ color: '#7bdd63 ' })
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建图层
|
||||||
|
* @param {*} pointObj 坐标数组
|
||||||
|
* @param {*} type 类型
|
||||||
|
* @param {*} id 唯一id
|
||||||
|
* @param {*} name 名称
|
||||||
|
* */
|
||||||
|
// 共享 source 和图层(全局一次性创建)
|
||||||
|
const sharedSource = new VectorSource();
|
||||||
|
const sharedLayer = new VectorLayer({
|
||||||
|
source: sharedSource,
|
||||||
|
renderMode: 'image' // 提高渲染性能
|
||||||
|
} as any);
|
||||||
|
// id => Feature 映射表
|
||||||
|
const featureMap: Record<string, Feature> = {};
|
||||||
|
const creatPoint = (pointObj: Array<any>, type: string, id: string, name?: string, status?: string) => {
|
||||||
|
let geometry;
|
||||||
|
|
||||||
|
if (type === 'Point') {
|
||||||
|
geometry = new Point(fromLonLat(pointObj));
|
||||||
|
} else if (type === 'Polygon') {
|
||||||
|
const coords = pointObj.map((arr: any) => fromLonLat(arr));
|
||||||
|
geometry = new Polygon([coords]);
|
||||||
|
}
|
||||||
|
|
||||||
|
const feature = new Feature({ geometry });
|
||||||
|
const zoom = map.getView().getZoom();
|
||||||
|
const scale = Math.max(zoom / 10, 1); // 缩放比例,根据需要调整公式
|
||||||
|
const pointStyle = new Style({
|
||||||
|
image: new Circle({
|
||||||
|
radius: 2,
|
||||||
|
fill: new Fill({ color: 'red' })
|
||||||
|
}),
|
||||||
|
text: new Text({
|
||||||
|
font: '12px Microsoft YaHei',
|
||||||
|
text: name,
|
||||||
|
scale,
|
||||||
|
fill: new Fill({ color: '#7bdd63' })
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
const polygonStyle = status == '2' ? successStyle(name, scale) : defaultStyle(name || '', scale);
|
||||||
|
|
||||||
|
feature.setStyle(type === 'Point' ? pointStyle : polygonStyle);
|
||||||
|
feature.set('name', name || ''); // 设置名称
|
||||||
|
feature.set('status', status || ''); // 设置完成状态 2为完成 其他为未完成
|
||||||
|
feature.set('id', id || '');
|
||||||
|
// 缓存 feature(用于后续判断)
|
||||||
|
featureMap[id] = feature;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 添加点到地图
|
||||||
|
const addPointToMap = (features: Array<any>) => {
|
||||||
|
features.forEach((item: any) => {
|
||||||
|
const fid = item.id;
|
||||||
|
|
||||||
|
// 没创建过就先创建
|
||||||
|
if (!featureMap[fid]) {
|
||||||
|
creatPoint(item.positions, item.type, fid, item.name, item.status);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加到共享 source 中(避免重复添加)
|
||||||
|
const feature = featureMap[fid];
|
||||||
|
if (!sharedSource.hasFeature(feature)) {
|
||||||
|
sharedSource.addFeature(feature);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
// 地图初始化
|
||||||
|
initOLMap();
|
||||||
|
map.addLayer(sharedLayer);
|
||||||
|
const canvas = document.createElement('canvas');
|
||||||
|
const ctx = canvas.getContext('2d', { willReadFrequently: true });
|
||||||
|
|
||||||
|
getList();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.ol-map {
|
||||||
|
height: 100vh;
|
||||||
|
width: 100%;
|
||||||
|
position: absolute;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
.header {
|
||||||
|
height: 90px;
|
||||||
|
width: 100%;
|
||||||
|
position: absolute;
|
||||||
|
z-index: 2;
|
||||||
|
}
|
||||||
|
.aside {
|
||||||
|
position: absolute;
|
||||||
|
top: 10%;
|
||||||
|
left: 30px;
|
||||||
|
width: 300px;
|
||||||
|
height: 70vh;
|
||||||
|
background-color: rgba(255, 255, 255, 0.8);
|
||||||
|
z-index: 3;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
.submit {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 70px;
|
||||||
|
right: 70px;
|
||||||
|
z-index: 3;
|
||||||
|
}
|
||||||
|
</style>
|
Reference in New Issue
Block a user