明树Git Lab
Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
J
jt_front
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Administrator
jt_front
Commits
1d2b693a
Commit
1d2b693a
authored
Dec 03, 2025
by
chenron
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
角色管理
parent
89517cb8
Changes
16
Hide whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
1147 additions
and
227 deletions
+1147
-227
CommonComplete.vue
src/components/CommonComplete.vue
+19
-5
CommonMap.vue
src/components/CommonMap.vue
+71
-65
CommonPlant.vue
src/components/CommonPlant.vue
+7
-2
CommonTotal.vue
src/components/CommonTotal.vue
+5
-1
commonForm.vue
src/components/common/commonForm.vue
+13
-5
commonTable.vue
src/components/common/commonTable.vue
+33
-1
index.js
src/router/index.js
+7
-0
Construct.vue
src/views/homePage/components/Construct.vue
+19
-12
Operation.vue
src/views/homePage/components/Operation.vue
+32
-23
ProjectApproval.vue
src/views/homePage/components/ProjectApproval.vue
+32
-10
trialOperations.vue
src/views/homePage/components/trialOperations.vue
+160
-0
index.vue
src/views/homePage/index.vue
+25
-24
departManage.vue
src/views/systemManage/departManage.vue
+42
-17
menuManage.vue
src/views/systemManage/menuManage.vue
+600
-0
roleManage.vue
src/views/systemManage/roleManage.vue
+78
-49
userManage.vue
src/views/systemManage/userManage.vue
+4
-13
No files found.
src/components/CommonComplete.vue
View file @
1d2b693a
...
...
@@ -6,17 +6,25 @@
<div
class=
"card-value-top"
>
<div>
<p
class=
"pro-title"
>
{{
item
.
protitle
}}
</p>
<p
class=
"pro-value"
>
{{
item
.
proValue
}}
<span>
亿元
</span></p>
<p
class=
"pro-value"
>
{{
item
.
proValue
}}
<span
v-if=
"item.proValue !== '*'"
>
亿元
</span>
</p>
</div>
<div>
<p
class=
"pro-title"
>
{{
item
.
thirdTtile
}}
</p>
<p
class=
"pro-value"
>
{{
item
.
thirdValue
}}
<span>
亿元
</span></p>
<p
class=
"pro-value"
>
{{
item
.
thirdValue
}}
<span
v-if=
"item.thirdValue !== '*'"
>
亿元
</span>
</p>
</div>
</div>
<div
class=
"card-value-bottom"
>
<div>
<p
class=
"pro-title"
>
2025年累计完成
</p>
<p
class=
"pro-value"
>
112.1
<span>
亿元
</span></p>
<p
class=
"pro-value"
>
{{
item
.
cumulativeValue
}}
<span
v-if=
"item.cumulativeValue !== '*'"
>
亿元
</span>
</p>
</div>
<div
class=
"value-bottom-right"
>
<p
class=
"comparison"
>
累计同期环比
</p>
...
...
@@ -29,8 +37,14 @@
class=
"trend-icon"
:class=
"
{ 'down-trend': item.title === '运营成本' }"
>
<Bottom
v-if=
"item.title === '运营成本'"
/>
<Top
v-else
/>
<span
v-if=
"item.compareValue !== '*'"
>
<Bottom
v-if=
"
item.title === '运营成本' || item.title === '利润总额'
"
/>
<Top
v-else
/>
</span>
</el-icon>
</p>
</div>
...
...
src/components/CommonMap.vue
View file @
1d2b693a
...
...
@@ -5,7 +5,7 @@
</
template
>
<
script
setup
>
import
AMapLoader
from
"@amap/amap-jsapi-loader"
;
import
{
nextTick
,
onMounted
,
ref
}
from
"vue"
;
import
{
nextTick
,
onMounted
,
re
active
,
re
f
}
from
"vue"
;
import
gansuLine
from
"./newLine.json"
;
let
map
=
null
;
window
.
_AMapSecurityConfig
=
{
...
...
@@ -13,6 +13,7 @@ window._AMapSecurityConfig = {
};
// 初始化地图
const
handleInitMap
=
()
=>
{
let
selectName
=
sessionStorage
.
getItem
(
"selectedContentBtn"
);
AMapLoader
.
load
({
key
:
"c691971f068b92c897fb908c4ddef6d4"
,
// 申请好的Web端开发者Key
version
:
"2.0"
,
...
...
@@ -38,7 +39,7 @@ const handleInitMap = () => {
// });
handleDistrict
();
addPolylines
();
handleAddMarket
();
handleAddMarket
(
selectName
);
})
.
catch
((
e
)
=>
{
// console.log(e);
...
...
@@ -163,80 +164,85 @@ const addPolylines = () => {
map
.
add
(
geojsonObj
);
};
// 添加标记
const
handleAddMarket
=
()
=>
{
const
markers
=
[];
const
positionsList
=
[
{
number
:
1
,
position
:
[
116.405467
,
39.907761
],
},
{
number
:
5
,
position
:
[
114.298569
,
30.584354
],
},
{
number
:
6
,
position
:
[
117.190186
,
39.125595
],
},
{
number
:
4
,
position
:
[
112.549248
,
37.857014
],
},
{
number
:
8
,
position
:
[
123.429092
,
41.796768
],
},
{
number
:
2
,
position
:
[
121.472641
,
31.231707
],
},
{
number
:
7
,
position
:
[
119.306236
,
26.075302
],
},
{
number
:
9
,
position
:
[
106.504959
,
29.533155
],
},
{
number
:
6
,
position
:
[
91.1145
,
29.64415
],
},
{
number
:
3
,
position
:
[
101.77782
,
36.61729
],
},
{
number
:
8
,
position
:
[
87.61688
,
43.82663
],
},
{
number
:
10
,
position
:
[
111.75199
,
40.84149
],
},
{
number
:
9
,
position
:
[
126.642464
,
45.756966
],
},
];
let
currentMarkers
=
[];
// 存储当前显示的标记
const
handleAddMarket
=
(
selectName
)
=>
{
// 清除之前的所有标记
if
(
currentMarkers
.
length
>
0
)
{
map
.
remove
(
currentMarkers
);
currentMarkers
=
[];
}
// 根据不同状态定义标记数据
const
markerData
=
{
建设
:
[
// 安徽
{
number
:
1
,
position
:
[
117.27
,
31.86
]
},
// 广东
{
number
:
1
,
position
:
[
113.2806
,
23.1252
]
},
// 陕西
{
number
:
2
,
position
:
[
112.5492
,
37.857
]
},
// 广西
{
number
:
2
,
position
:
[
108.3664
,
22.8177
]
},
// 山东
{
number
:
2
,
position
:
[
121.6167
,
38.9167
]
},
// 河北
{
number
:
1
,
position
:
[
114.52
,
38.05
]
},
],
试运营
:
[
// 四川
{
number
:
2
,
position
:
[
117.27
,
31.86
]
},
// 山东
{
number
:
3
,
position
:
[
121.6167
,
38.9167
]
},
// 云南
{
number
:
1
,
position
:
[
102.7333
,
25.05
]
},
// 陕西
{
number
:
3
,
position
:
[
112.5492
,
37.857
]
},
// 广西
{
number
:
1
,
position
:
[
108.3664
,
22.8177
]
},
// 湖北
{
number
:
1
,
position
:
[
114.3052
,
30.5929
]
},
],
运营
:
[
// 四川
{
number
:
1
,
position
:
[
117.27
,
31.86
]
},
// 山东
{
number
:
1
,
position
:
[
121.6167
,
38.9167
]
},
// 湖北
{
number
:
1
,
position
:
[
114.3052
,
30.5929
]
},
],
退出
:
[
// 河南
{
number
:
3
,
position
:
[
113.65
,
34.7667
]
},
],
立项
:
[],
// 立项没有标记
};
for
(
var
i
=
0
,
marker
;
i
<
positionsList
.
length
;
i
++
)
{
marker
=
new
AMap
.
Marker
({
const
positionsList
=
markerData
[
selectName
]
||
[];
// 创建新的标记
for
(
var
i
=
0
;
i
<
positionsList
.
length
;
i
++
)
{
const
marker
=
new
AMap
.
Marker
({
map
:
map
,
position
:
positionsList
[
i
].
position
,
// icon: "//a.amap.com/jsapi_demos/static/demo-center/icons/poi-marker-default.png",
offset
:
new
AMap
.
Pixel
(
-
13
,
-
30
),
content
:
""
+
'<div class="custom-content-marker">'
+
'<img src="//a.amap.com/jsapi_demos/static/demo-center/icons/poi-marker-default.png">'
+
`<div class="anchorPoint"
"
>
${
positionsList
[
i
].
number
}
</div>`
+
`<div class="anchorPoint">
${
positionsList
[
i
].
number
}
</div>`
+
"</div>"
,
});
m
arkers
.
push
(
marker
);
currentM
arkers
.
push
(
marker
);
}
map
.
add
([
markers
]);
};
// 暴露更新标记的方法给父组件
const
updateMarkers
=
(
selectName
)
=>
{
handleAddMarket
(
selectName
);
};
// 暴露方法给父组件
defineExpose
({
updateMarkers
,
});
onMounted
(()
=>
{
handleInitMap
();
});
...
...
src/components/CommonPlant.vue
View file @
1d2b693a
...
...
@@ -6,11 +6,16 @@
<div
class=
"amount"
>
<div>
<p
class=
"amount-title"
>
实际完成金额
</p>
<p
class=
"amount-value"
>
2.87
<span>
亿元
</span></p>
<p
class=
"amount-value"
>
{{
item
.
actualValue
}}
<span
v-if=
"item.actualValue !== '*'"
>
亿元
</span>
</p>
</div>
<div>
<p
class=
"amount-title"
>
计划完成金额
</p>
<p
class=
"amount-value"
>
4.21
<span>
亿元
</span></p>
<p
class=
"amount-value"
>
{{
item
.
planValue
}}
<span
v-if=
"item.planValue !== '*'"
>
亿元
</span>
</p>
</div>
</div>
</div>
...
...
src/components/CommonTotal.vue
View file @
1d2b693a
...
...
@@ -137,12 +137,16 @@ onMounted(() => {});
display: flex;
.stat-card {
.vw(width, 180);
.vh(height, 90);
.vw(border-radius, 5);
.vw(padding, 10);
.vw(margin-right,10);
background-image: url("@/assets/images/total2.png");
background-repeat: no-repeat;
background-size: contain;
background-size: 100% 100%;
display: flex;
flex-direction: column;
justify-content: space-between;
.stat-card-title {
.font(12);
}
...
...
src/components/common/commonForm.vue
View file @
1d2b693a
...
...
@@ -394,7 +394,10 @@
</el-row>
<!-- 表单操作按钮 -->
<el-form-item
v-if=
"config.showButtons !== false"
>
<el-form-item
v-if=
"config.showButtons !== false"
class=
"form-buttons"
>
<el-button
v-if=
"config.showReset !== false"
@
click=
"handleReset"
>
{{ config.resetText || "重置" }}
</el-button>
<el-button
v-if=
"config.showSubmit !== false"
type=
"primary"
...
...
@@ -403,9 +406,6 @@
>
{{ config.submitText || "提交" }}
</el-button>
<el-button
v-if=
"config.showReset !== false"
@
click=
"handleReset"
>
{{ config.resetText || "重置" }}
</el-button>
<el-button
v-for=
"btn in config.customButtons"
:key=
"btn.key"
...
...
@@ -697,6 +697,14 @@ onMounted(() => {
margin-bottom: 18px;
}
.form-buttons {
:deep(.el-form-item__content) {
display: flex;
justify-content: flex-end;
gap: 10px;
}
}
:deep(.el-input-number) {
width: 100%;
}
...
...
@@ -715,7 +723,7 @@ onMounted(() => {
:deep(.el-form-item) {
&:last-child {
.el-form-item__content {
justify-content: flex-end;
//
justify-content: flex-end;
}
}
}
...
...
src/components/common/commonTable.vue
View file @
1d2b693a
...
...
@@ -13,7 +13,7 @@
<el-table
style=
"width: 100%"
:data=
"tableData"
:height=
"
t
ableHeight"
:height=
"
computedT
ableHeight"
:max-height=
"maxHeight"
:stripe=
"stripe"
border
...
...
@@ -170,6 +170,21 @@ const props = defineProps({
type
:
[
String
,
Number
],
default
:
"auto"
,
},
// 是否自动计算表格高度
autoHeight
:
{
type
:
Boolean
,
default
:
false
,
},
// 自动计算时的最大显示行数
maxRows
:
{
type
:
Number
,
default
:
10
,
},
// 行高(像素)
rowHeight
:
{
type
:
Number
,
default
:
45
,
},
// 表格最大高度
maxHeight
:
[
String
,
Number
],
// 是否为斑马纹表格
...
...
@@ -375,6 +390,23 @@ const tableData = computed(() => {
return
props
.
data
;
});
// 自动计算表格高度
const
computedTableHeight
=
computed
(()
=>
{
if
(
!
props
.
autoHeight
)
{
return
props
.
tableHeight
;
}
const
headerHeight
=
50
;
const
paginationHeight
=
props
.
pagination
?
50
:
0
;
const
baseHeight
=
headerHeight
+
paginationHeight
;
// 如果数据超过最大行数,固定显示最大行数的高度;如果数据不超过最大行数,按实际行数计算高度
const
actualRows
=
Math
.
min
(
tableData
.
value
.
length
,
props
.
maxRows
);
const
contentHeight
=
actualRows
*
props
.
rowHeight
;
return
`
${
baseHeight
+
contentHeight
}
px`
;
});
// 监听器
watch
(
()
=>
props
.
currentPage
,
...
...
src/router/index.js
View file @
1d2b693a
...
...
@@ -65,6 +65,13 @@ const routes = [
title
:
'roleManage'
,
component
:
()
=>
import
(
'@/views/systemManage/roleManage.vue'
),
meta
:
{
menuName
:
'角色管理'
,}
},
{
path
:
'/systemManage/menuManage'
,
name
:
'菜单管理'
,
title
:
'menuManage'
,
component
:
()
=>
import
(
'@/views/systemManage/menuManage.vue'
),
meta
:
{
menuName
:
'菜单管理'
,}
}
]
},
...
...
src/views/homePage/components/Construct.vue
View file @
1d2b693a
...
...
@@ -44,29 +44,36 @@
<
script
setup
>
import
Map
from
"@/components/CommonMap.vue"
;
import
CommonTotal
from
"@/components/CommonTotal.vue"
;
import
{
reactive
,
ref
,
onMounted
,
onUnmounted
,
shallowReactive
,
defineOptions
}
from
"vue"
;
import
{
reactive
,
ref
,
onMounted
,
onUnmounted
,
shallowReactive
,
defineOptions
,
}
from
"vue"
;
import
CircleProgress
from
"./CircleProgress.vue"
;
// 定义组件名称,用于keep-alive缓存
defineOptions
({
name
:
'Construct'
name
:
"Construct"
,
});
// 使用shallowReactive减少深层响应式开销
const
projectList
=
shallowReactive
([
{
title
:
"总个数(个)"
,
value
:
"
59
"
},
{
title
:
"总投资(亿元)"
,
value
:
"
2733.3
5"
},
{
title
:
"总规模(公里)"
,
value
:
"
5116.72
"
},
{
title
:
"总个数(个)"
,
value
:
"
10
"
},
{
title
:
"总投资(亿元)"
,
value
:
"
1334.0
5"
},
{
title
:
"总规模(公里)"
,
value
:
"
1051.56
"
},
]);
const
investmentList
=
shallowReactive
([
{
title
:
"10月完成投资(亿元)"
,
value
:
"
0
"
},
{
title
:
"2025年完成投资(亿元)"
,
value
:
"
19.725
"
},
{
title
:
"累计完成投资(亿元)"
,
value
:
"
807.56
"
},
{
title
:
"10月完成投资(亿元)"
,
value
:
"
*
"
},
{
title
:
"2025年完成投资(亿元)"
,
value
:
"
*
"
},
{
title
:
"累计完成投资(亿元)"
,
value
:
"
*
"
},
]);
// recycleList
const
recycleList
=
shallowReactive
([
{
title
:
"10月完成投资(亿元)"
,
value
:
"
0
"
},
{
title
:
"2025年完成投资(亿元)"
,
value
:
"
2.98
"
},
{
title
:
"完成率"
,
value
:
"
50.2%
"
},
{
title
:
"10月完成投资(亿元)"
,
value
:
"
*
"
},
{
title
:
"2025年完成投资(亿元)"
,
value
:
"
*
"
},
{
title
:
"完成率"
,
value
:
"
*
"
},
]);
</
script
>
...
...
@@ -120,7 +127,7 @@ const recycleList = shallowReactive([
font-family: "DIN";
}
.progress-image {
.vw(width,
52
0);
.vw(width,
43
0);
.vh(height,85);
background-image: url("@/assets/images/箭头.png");
background-repeat: no-repeat;
...
...
src/views/homePage/components/Operation.vue
View file @
1d2b693a
...
...
@@ -38,57 +38,66 @@ import Map from "@/components/CommonMap.vue";
import
CommonTotal
from
"@/components/CommonTotal.vue"
;
import
CommonComplete
from
"@/components/CommonComplete.vue"
;
import
CommonPlant
from
"@/components/CommonPlant.vue"
;
import
{
shallowReactive
,
ref
,
onMounted
,
onUnmounted
,
defineOptions
}
from
"vue"
;
import
{
shallowReactive
,
ref
,
onMounted
,
onUnmounted
,
defineOptions
,
}
from
"vue"
;
// 定义组件名称,用于keep-alive缓存
defineOptions
({
name
:
'Operation'
name
:
"Operation"
,
});
// 使用shallowReactive减少深层响应式开销
const
projectList
=
shallowReactive
([
{
title
:
"总个数(个)"
,
value
:
"
59
"
},
{
title
:
"总投资(亿元)"
,
value
:
"
2733.35
"
},
{
title
:
"总规模(公里)"
,
value
:
"
5116.7
2"
},
{
title
:
"总个数(个)"
,
value
:
"
2
"
},
{
title
:
"总投资(亿元)"
,
value
:
"
114.23
"
},
{
title
:
"总规模(公里)"
,
value
:
"
233.2
2"
},
]);
const
investmentList
=
shallowReactive
([
{
title
:
"10月完成投资(亿元)"
,
value
:
"
0
"
},
{
title
:
"2025年完成投资(亿元)"
,
value
:
"
19.725
"
},
{
title
:
"累计完成投资(亿元)"
,
value
:
"
807.56
"
},
{
title
:
"10月完成投资(亿元)"
,
value
:
"
*
"
},
{
title
:
"2025年完成投资(亿元)"
,
value
:
"
*
"
},
{
title
:
"累计完成投资(亿元)"
,
value
:
"
*
"
},
]);
const
recycleList
=
shallowReactive
([
{
title
:
"10月完成投资(亿元)"
,
value
:
"
0
"
},
{
title
:
"2025年完成投资(亿元)"
,
value
:
"
2.98
"
},
{
title
:
"完成率"
,
value
:
"
50.2%
"
},
{
title
:
"10月完成投资(亿元)"
,
value
:
"
*
"
},
{
title
:
"2025年完成投资(亿元)"
,
value
:
"
*
"
},
{
title
:
"完成率"
,
value
:
"
*
"
},
]);
const
operationList
=
shallowReactive
([
{
title
:
"营业收入完成进度"
,
value
:
"
68.1%
"
},
{
title
:
"运营成本完成进度"
,
value
:
"
68.1%
"
},
{
title
:
"利润总额完成进度"
,
value
:
"
68.1%
"
},
{
title
:
"营业收入完成进度"
,
value
:
"
*"
,
actualValue
:
"*"
,
planValue
:
"*
"
},
{
title
:
"运营成本完成进度"
,
value
:
"
*"
,
actualValue
:
"*"
,
planValue
:
"*
"
},
{
title
:
"利润总额完成进度"
,
value
:
"
*"
,
actualValue
:
"*"
,
planValue
:
"*
"
},
]);
const
completeList
=
shallowReactive
([
{
title
:
"营业收入"
,
protitle
:
"11月完成"
,
proValue
:
"
1.1
"
,
proValue
:
"
*
"
,
thirdTtile
:
"第三季度完成"
,
thirdValue
:
"4.21"
,
compareValue
:
"+1.2%"
,
thirdValue
:
"*"
,
compareValue
:
"*"
,
cumulativeValue
:
"*"
,
},
{
title
:
"运营成本"
,
protitle
:
"11月完成"
,
proValue
:
"
47.98
"
,
proValue
:
"
*
"
,
thirdTtile
:
"第三季度完成"
,
thirdValue
:
"5.75"
,
compareValue
:
"-0.5%"
,
thirdValue
:
"*"
,
compareValue
:
"*"
,
cumulativeValue
:
"*"
,
},
{
title
:
"利润总额"
,
protitle
:
"11月完成"
,
proValue
:
"
9.90
"
,
proValue
:
"
*
"
,
thirdTtile
:
"第三季度完成"
,
thirdValue
:
"23.52"
,
compareValue
:
"+1.2%"
,
thirdValue
:
"*"
,
compareValue
:
"*"
,
cumulativeValue
:
"*"
,
},
]);
</
script
>
...
...
src/views/homePage/components/ProjectApproval.vue
View file @
1d2b693a
...
...
@@ -2,17 +2,25 @@
<div
class=
"project-container"
>
<CommonTotal
:numberList=
"initiationList"
/>
</div>
<Map
/>
<Map
ref=
"mapRef"
/>
</
template
>
<
script
setup
>
import
CommonTotal
from
"@/components/CommonTotal.vue"
;
import
Map
from
"@/components/CommonMap.vue"
;
import
{
onMounted
,
reactive
,
watch
,
ref
,
computed
,
shallowRef
,
defineOptions
}
from
"vue"
;
import
{
onMounted
,
reactive
,
watch
,
ref
,
computed
,
shallowRef
,
defineOptions
,
}
from
"vue"
;
// 定义组件名称,用于keep-alive缓存
defineOptions
({
name
:
'ProjectApproval'
name
:
"ProjectApproval"
,
});
const
props
=
defineProps
({
...
...
@@ -21,12 +29,14 @@ const props = defineProps({
default
:
"立项"
,
},
});
const
mapRef
=
ref
(
null
);
// 使用静态数据避免重复创建
const
STATIC_DATA
=
{
立项
:
[
{
title
:
"总个数(个)"
,
value
:
"
59
"
},
{
title
:
"总投资(亿元)"
,
value
:
"
2733.35
"
},
{
title
:
"总规模(公里)"
,
value
:
"
5116.72
"
},
{
title
:
"总个数(个)"
,
value
:
"
0
"
},
{
title
:
"总投资(亿元)"
,
value
:
"
0
"
},
{
title
:
"总规模(公里)"
,
value
:
"
0
"
},
],
转让
:
[
{
title
:
"总个数(个)"
,
value
:
"59"
},
...
...
@@ -35,10 +45,10 @@ const STATIC_DATA = {
{
title
:
"累计完成投资(亿元)"
,
value
:
"3116.44"
},
],
退出
:
[
{
title
:
"总个数(个)"
,
value
:
"
59
"
},
{
title
:
"总投资(亿元)"
,
value
:
"
2733.35
"
},
{
title
:
"总规模(公里)"
,
value
:
"
5116.72
"
},
{
title
:
"累计完成投资(亿元)"
,
value
:
"
3116.44
"
},
{
title
:
"总个数(个)"
,
value
:
"
3
"
},
{
title
:
"总投资(亿元)"
,
value
:
"
141.29
"
},
{
title
:
"总规模(公里)"
,
value
:
"
108.35
"
},
{
title
:
"累计完成投资(亿元)"
,
value
:
"
0
"
},
],
};
...
...
@@ -46,6 +56,18 @@ const STATIC_DATA = {
const
initiationList
=
computed
(()
=>
{
return
STATIC_DATA
[
props
.
currentName
]
||
STATIC_DATA
.
立项
;
});
// 监听props.currentName的变化
watch
(
()
=>
props
.
currentName
,
(
newValue
,
oldValue
)
=>
{
// 调用地图组件的updateMarkers方法来更新标记
if
(
mapRef
.
value
&&
mapRef
.
value
.
updateMarkers
)
{
mapRef
.
value
.
updateMarkers
(
newValue
);
}
},
{
immediate
:
true
}
);
</
script
>
<
style
scoped
lang=
"less"
>
...
...
src/views/homePage/components/trialOperations.vue
0 → 100644
View file @
1d2b693a
<
template
>
<div
class=
"construct-container"
>
<div
class=
"construct-left"
>
<div
class=
"tag-image"
>
<img
src=
"@/assets/images/建设.png"
/>
</div>
<div
class=
"construct-left-map"
>
<Map
/>
</div>
</div>
<div
class=
"construct-right"
>
<div>
<div
class=
"info-title"
>
项目概况
</div>
<CommonTotal
:numberList=
"projectList"
/>
</div>
<div>
<div
class=
"info-title"
>
投资完成情况
</div>
<CommonTotal
:numberList=
"investmentList"
/>
</div>
<div>
<div
class=
"info-title"
>
经营计划完成情况
</div>
<CommonComplete
:numberList=
"completeList"
/>
</div>
<div>
<div
class=
"info-title"
>
投资回收完成情况
</div>
<CommonTotal
:numberList=
"recycleList"
/>
</div>
<div>
<div
class=
"info-title"
>
2025年经营计划完成进度
</div>
<CommonPlant
:numberList=
"operationList"
/>
</div>
</div>
</div>
</
template
>
<
script
setup
>
import
Map
from
"@/components/CommonMap.vue"
;
import
CommonTotal
from
"@/components/CommonTotal.vue"
;
import
CommonComplete
from
"@/components/CommonComplete.vue"
;
import
CommonPlant
from
"@/components/CommonPlant.vue"
;
import
{
shallowReactive
,
ref
,
onMounted
,
onUnmounted
,
defineOptions
,
}
from
"vue"
;
// 定义组件名称,用于keep-alive缓存
defineOptions
({
name
:
"Operation"
,
});
// 使用shallowReactive减少深层响应式开销
const
projectList
=
shallowReactive
([
{
title
:
"总个数(个)"
,
value
:
"9"
},
{
title
:
"总投资(亿元)"
,
value
:
"2733.35"
},
{
title
:
"总规模(公里)"
,
value
:
"5116.72"
},
]);
const
investmentList
=
shallowReactive
([
{
title
:
"10月完成投资(亿元)"
,
value
:
"*"
},
{
title
:
"2025年完成投资(亿元)"
,
value
:
"*"
},
{
title
:
"累计完成投资(亿元)"
,
value
:
"*"
},
]);
const
recycleList
=
shallowReactive
([
{
title
:
"10月完成投资(亿元)"
,
value
:
"*"
},
{
title
:
"2025年完成投资(亿元)"
,
value
:
"*"
},
{
title
:
"完成率"
,
value
:
"*"
},
]);
const
operationList
=
shallowReactive
([
{
title
:
"营业收入完成进度"
,
value
:
"85.81%"
,
actualValue
:
"38.86"
,
planValue
:
"45.27"
,
},
{
title
:
"运营成本完成进度"
,
value
:
"79.60%"
,
actualValue
:
"20.91"
,
planValue
:
"26.27"
,
},
{
title
:
"利润总额完成进度"
,
value
:
"77.59%"
,
actualValue
:
"-7.94"
,
planValue
:
"-10.23"
,
},
]);
const
completeList
=
shallowReactive
([
{
title
:
"营业收入"
,
protitle
:
"11月完成"
,
proValue
:
"*"
,
thirdTtile
:
"第三季度完成"
,
thirdValue
:
"31.71"
,
compareValue
:
"+3.78%"
,
cumulativeValue
:
"38.86"
,
},
{
title
:
"运营成本"
,
protitle
:
"11月完成"
,
proValue
:
"*"
,
thirdTtile
:
"第三季度完成"
,
thirdValue
:
"16.99"
,
compareValue
:
"-14.73%"
,
cumulativeValue
:
"20.91"
,
},
{
title
:
"利润总额"
,
protitle
:
"11月完成"
,
proValue
:
"*"
,
thirdTtile
:
"第三季度完成"
,
thirdValue
:
"-5.91"
,
compareValue
:
"−28.83%"
,
cumulativeValue
:
"-7.94"
,
},
]);
</
script
>
<
style
scoped
lang=
"less"
>
.construct-container {
display: flex;
.construct-left {
width: 100%;
height: 100%;
.tag-image {
img {
.vw(width, 85);
}
}
.construct-left-map {
.vh(height, 700);
.vh(padding-top, 4);
}
}
.construct-right {
display: flex;
flex-direction: column;
justify-content: space-between;
.info-title {
.vw(width, 180);
.vh(height, 30);
.vh(line-height, 30);
.font(16);
.vw(padding-left,20);
.vh(margin-bottom,15);
.vh(margin-top,15);
text-align: left;
color: #fff;
white-space: nowrap;
font-family: YouSheBiaoTiYuan;
background-image: url("@/assets/images/tag.png");
background-repeat: no-repeat;
background-size: cover;
background-position: center;
background-size: 100% 100%;
}
}
}
</
style
>
src/views/homePage/index.vue
View file @
1d2b693a
...
...
@@ -14,7 +14,7 @@
:class=
"
{ active: selectedLeftBtn === 'risk' }"
@click="selectLeftBtn('risk')"
>
固定
风险
投资
固定
资产
投资
</div>
</div>
<div
class=
"header-middile"
>
...
...
@@ -55,17 +55,14 @@
>
{{
item
.
name
}}
</span>
</div>
<keep-alive
include=
"ProjectApproval,Construct,Operation"
>
<keep-alive
include=
"ProjectApproval,Construct,Operation
,TrialOperations
"
>
<ProjectApproval
:currentName=
"selectedContentName"
v-if=
"
selectedContentBtn === 1 ||
selectedContentBtn === 4 ||
selectedContentBtn === 5
"
v-if=
"selectedContentBtn === 1 || selectedContentBtn === 6"
/>
<Construct
v-else-if=
"selectedContentBtn === 2"
/>
<Operation
v-else
/>
<Operation
v-else-if=
"selectedContentBtn === 4"
/>
<TrialOperations
v-else-if=
"selectedContentBtn === 3"
/>
</keep-alive>
</div>
<div
class=
"bottom"
></div>
...
...
@@ -76,7 +73,8 @@
import
Construct
from
"./components/Construct.vue"
;
import
ProjectApproval
from
"./components/ProjectApproval.vue"
;
import
Operation
from
"./components/Operation.vue"
;
import
{
reactive
,
ref
,
nextTick
}
from
"vue"
;
import
TrialOperations
from
"./components/trialOperations.vue"
;
import
{
reactive
,
ref
,
nextTick
,
watch
,
onMounted
}
from
"vue"
;
const
selectedLeftBtn
=
ref
(
"equity"
);
const
selectedRightBtn
=
ref
(
""
);
...
...
@@ -98,14 +96,18 @@ const navList = reactive([
},
{
index
:
3
,
name
:
"运营"
,
name
:
"
试
运营"
,
},
{
index
:
4
,
name
:
"
转让
"
,
name
:
"
运营
"
,
},
// {
// index: 5,
// name: "转让",
// },
{
index
:
5
,
index
:
6
,
name
:
"退出"
,
},
]);
...
...
@@ -123,21 +125,14 @@ const selectRightBtn = (btn) => {
// 添加防抖功能,避免频繁切换造成的性能问题
let
debounceTimer
=
null
;
const
selectContentBtn
=
(
item
)
=>
{
// 清除之前的定时器
if
(
debounceTimer
)
{
clearTimeout
(
debounceTimer
);
}
// 使用防抖延迟切换
debounceTimer
=
setTimeout
(()
=>
{
selectedContentBtn
.
value
=
item
.
index
;
selectedContentName
.
value
=
item
.
name
;
// 使用nextTick确保DOM更新完成
nextTick
(()
=>
{
// 可以在这里添加其他需要延迟执行的逻辑
});
},
100
);
// 100ms防抖延迟
sessionStorage
.
setItem
(
"selectedContentBtn"
,
selectedContentName
.
value
);
},
100
);
};
// 暂时注释未使用的函数,避免lint警告
...
...
@@ -188,6 +183,11 @@ const toggleFullscreen = () => {
isFullscreen
.
value
=
!
isFullscreen
.
value
;
};
// 页面初始化时设置sessionStorage
onMounted
(()
=>
{
sessionStorage
.
setItem
(
"selectedContentBtn"
,
selectedContentName
.
value
);
});
// 监听全屏变化事件
window
.
addEventListener
(
"fullscreenchange"
,
()
=>
{
if
(
!
document
.
fullscreenElement
)
{
...
...
@@ -348,7 +348,7 @@ window.addEventListener("fullscreenchange", () => {
}
// 退出按钮
:nth-child(
5
) {
:nth-child(
6
) {
background-repeat: no-repeat;
background-size: 80% 80%;
background-position: center;
...
...
@@ -367,7 +367,8 @@ window.addEventListener("fullscreenchange", () => {
// 中间按钮(建设、运营、转止)
:nth-child(2),
:nth-child(3),
:nth-child(4) {
:nth-child(4),
:nth-child(5) {
background-repeat: no-repeat;
background-size: 80% 80%;
background-position: center;
...
...
@@ -381,7 +382,7 @@ window.addEventListener("fullscreenchange", () => {
background-image: url("@/assets/images/nav-hight-btn.png");
}
}
:nth-child(
5
) {
:nth-child(
6
) {
margin-left: -31px;
}
}
...
...
src/views/systemManage/departManage.vue
View file @
1d2b693a
...
...
@@ -2,8 +2,8 @@
<div
class=
"depart-manage"
v-loading=
"loading"
>
<div
class=
"search-origin"
>
<div
class=
"origin-title"
>
<h3>
组织
列表
</h3>
<
span
@
click=
"handleAdd"
>
+
新增组织
</span
>
<h3>
部门
列表
</h3>
<
!--
<span
@
click=
"handleAdd('parent')"
>
+
新增组织
</span>
--
>
</div>
<el-input
placeholder=
"请输入部门名称"
clearable
>
<template
#
prefix
>
...
...
@@ -18,6 +18,10 @@
</span>
<
template
#
dropdown
>
<el-dropdown-menu>
<el-dropdown-item
@
click=
"handleAdd"
><i
class=
"iconfont icon-tianjia"
></i
>
添加组织
</el-dropdown-item
>
<el-dropdown-item
@
click=
"handleOriginEdit"
><i
class=
"iconfont icon-bianji"
></i
>
编辑组织
</el-dropdown-item
...
...
@@ -47,12 +51,14 @@
<el-input
placeholder=
"请输入人员信息"
v-model=
"userName"
/>
</div>
<div>
<el-button
type=
"primary"
@
click=
"handleUserData"
>
查询
</el-button>
<el-button
type=
""
@
click=
"handleReset"
>
重置
</el-button>
<el-button
type=
"primary"
@
click=
"handleUserData"
>
查询
</el-button>
</div>
</div>
<common-table
:tableHeight=
"tableHeight"
:autoHeight=
"true"
:maxRows=
"10"
:rowHeight=
"40"
:data=
"tableData"
:columns=
"tableColumns"
:total=
"total"
...
...
@@ -103,17 +109,6 @@ const originTreeData = ref([]);
const
selectedNode
=
ref
(
null
);
const
userName
=
ref
(
""
);
// 计算表格高度
const
tableHeight
=
computed
(()
=>
{
const
headerHeight
=
50
;
const
paginationHeight
=
50
;
const
rowHeight
=
40
;
const
baseHeight
=
headerHeight
+
paginationHeight
;
const
maxRows
=
Math
.
min
(
tableData
.
value
.
length
,
10
);
const
contentHeight
=
maxRows
*
rowHeight
;
return
`
${
baseHeight
+
contentHeight
}
px`
;
});
// 数据转换函数
const
convertToTreeData
=
(
apiData
,
type
)
=>
{
if
(
type
===
"id"
)
{
...
...
@@ -250,11 +245,12 @@ const handleCurrentPageChange = (page) => {
const
handleAdd
=
()
=>
{
isEdit
.
value
=
false
;
dialogTitle
.
value
=
"新增组织"
;
dialogVisible
.
value
=
true
;
console
.
log
(
selectedNode
.
value
);
originForm
.
value
=
{
parentId
:
""
,
name
:
""
,
};
dialogVisible
.
value
=
true
;
};
let
currentID
=
ref
(
""
);
// 处理树节点点击事件
...
...
@@ -289,11 +285,12 @@ const handleOriginEdit = () => {
};
// 组织删除
const
handleDeleteOrigin
=
()
=>
{
console
.
log
(
selectedNode
.
value
);
if
(
selectedNode
.
value
===
null
)
{
ElMessage
.
warning
(
"请选择要删除的组织"
);
}
else
{
const
deleteItem
=
{
id
:
selectedNode
.
value
.
value
,
id
:
selectedNode
.
value
.
id
,
name
:
selectedNode
.
value
.
label
,
parentId
:
selectedNode
.
value
.
parentId
?
selectedNode
.
value
.
parentId
...
...
@@ -356,10 +353,12 @@ const handleFormSubmit = (formData) => {
const
handleFormReset
=
()
=>
{
dialogVisible
.
value
=
false
;
selectedNode
.
value
=
""
;
};
const
handleDialogClose
=
()
=>
{
dialogVisible
.
value
=
false
;
selectedNode
.
value
=
null
;
};
const
handleReset
=
()
=>
{
userName
.
value
=
""
;
...
...
@@ -466,6 +465,32 @@ onMounted(() => {
.tree-content {
margin-top: 20px;
position: relative;
.el-tree {
max-height: 700px;
overflow-y: auto;
// 只有当内容超过700px时才显示滚动条
&:not(:hover) {
scrollbar-width: none;
-ms-overflow-style: none;
&::-webkit-scrollbar {
display: none;
}
}
&:hover {
scrollbar-width: thin;
&::-webkit-scrollbar {
display: block;
width: 6px;
}
&::-webkit-scrollbar-thumb {
background-color: rgba(144, 147, 153, 0.3);
border-radius: 3px;
}
&::-webkit-scrollbar-track {
background-color: transparent;
}
}
}
}
.table-container {
...
...
src/views/systemManage/menuManage.vue
0 → 100644
View file @
1d2b693a
<
template
>
<div
class=
"user-manage"
v-loading=
"loading"
>
<div
class=
"search-form"
>
<commonForm
v-model=
"searchForm"
:config=
"searchConfig"
:items=
"searchItems"
@
submit=
"handleSearch"
@
reset=
"handleReset"
/>
</div>
<div
class=
"table-container"
>
<common-table
:maxRows=
"10"
:rowHeight=
"40"
:data=
"tableData"
:columns=
"tableColumns"
:total=
"total"
:current-page=
"currentPage"
:page-size=
"pageSize"
:indent=
"10"
title=
"菜单管理"
:border=
"true"
:tree-props=
"
{ children: 'children', hasChildren: 'hasChildren' }"
row-key="id"
default-expand-all
@size-change="handleSizeChange"
@current-page-change="handleCurrentPageChange"
>
<template
#
header-actions
>
<el-button
type=
"primary"
@
click=
"handleAdd"
>
新增
</el-button>
</
template
>
<
template
#
operations=
"{ row, index }"
>
<el-button
type=
"text"
size=
"small"
>
新增
</el-button>
<el-button
type=
"text"
size=
"small"
@
click=
"handleEdit(row, index)"
>
编辑
</el-button>
<el-button
type=
"text"
size=
"small"
@
click=
"handleDelete(row, index)"
>
删除
</el-button>
</
template
>
</common-table>
</div>
<el-dialog
v-model=
"dialogVisible"
:title=
"dialogTitle"
width=
"800px"
@
close=
"handleDialogClose"
>
<commonForm
v-model=
"userForm"
:config=
"formConfig"
:items=
"formItems"
:rules=
"formRules"
@
submit=
"handleFormSubmit"
@
reset=
"handleFormReset"
/>
</el-dialog>
</div>
</template>
<
script
setup
>
import
{
ref
,
reactive
,
onMounted
,
getCurrentInstance
,
computed
}
from
"vue"
;
import
{
ElMessage
,
ElMessageBox
}
from
"element-plus"
;
import
{
Plus
,
Edit
,
Delete
}
from
"@element-plus/icons-vue"
;
import
commonForm
from
"@/components/common/commonForm.vue"
;
import
CommonTable
from
"@/components/common/commonTable.vue"
;
import
{
da
}
from
"element-plus/es/locales.mjs"
;
// 模拟树形菜单数据
const
mockMenuData
=
[
{
id
:
1
,
name
:
"系统管理"
,
code
:
"system"
,
app
:
"管理平台"
,
type
:
"目录"
,
icon
:
"Setting"
,
order
:
1
,
createdAt
:
"2024-01-01"
,
children
:
[
{
id
:
11
,
name
:
"用户管理"
,
code
:
"user"
,
app
:
"管理平台"
,
type
:
"菜单"
,
icon
:
"User"
,
order
:
1
,
createdAt
:
"2024-01-01"
,
children
:
[
{
id
:
111
,
name
:
"用户列表"
,
code
:
"user-list"
,
app
:
"管理平台"
,
type
:
"菜单"
,
icon
:
"List"
,
order
:
1
,
createdAt
:
"2024-01-01"
,
},
{
id
:
112
,
name
:
"用户详情"
,
code
:
"user-detail"
,
app
:
"管理平台"
,
type
:
"菜单"
,
icon
:
"Document"
,
order
:
2
,
createdAt
:
"2024-01-01"
,
},
],
},
{
id
:
12
,
name
:
"角色管理"
,
code
:
"role"
,
app
:
"管理平台"
,
type
:
"菜单"
,
icon
:
"UserFilled"
,
order
:
2
,
createdAt
:
"2024-01-01"
,
},
{
id
:
13
,
name
:
"菜单管理"
,
code
:
"menu"
,
app
:
"管理平台"
,
type
:
"菜单"
,
icon
:
"Menu"
,
order
:
3
,
createdAt
:
"2024-01-01"
,
},
],
},
{
id
:
2
,
name
:
"业务管理"
,
code
:
"business"
,
app
:
"业务平台"
,
type
:
"目录"
,
icon
:
"Briefcase"
,
order
:
2
,
createdAt
:
"2024-01-01"
,
children
:
[
{
id
:
21
,
name
:
"项目管理"
,
code
:
"project"
,
app
:
"业务平台"
,
type
:
"菜单"
,
icon
:
"FolderOpened"
,
order
:
1
,
createdAt
:
"2024-01-01"
,
},
{
id
:
22
,
name
:
"审批管理"
,
code
:
"approval"
,
app
:
"业务平台"
,
type
:
"菜单"
,
icon
:
"Select"
,
order
:
2
,
createdAt
:
"2024-01-01"
,
},
],
},
{
id
:
3
,
name
:
"数据统计"
,
code
:
"statistics"
,
app
:
"分析平台"
,
type
:
"目录"
,
icon
:
"DataAnalysis"
,
order
:
3
,
createdAt
:
"2024-01-01"
,
children
:
[
{
id
:
31
,
name
:
"报表中心"
,
code
:
"report"
,
app
:
"分析平台"
,
type
:
"菜单"
,
icon
:
"PieChart"
,
order
:
1
,
createdAt
:
"2024-01-01"
,
},
],
},
];
const
{
proxy
}
=
getCurrentInstance
();
const
loading
=
ref
(
false
);
// 数据转换函数
const
convertToTreeData
=
(
apiData
)
=>
{
return
apiData
.
map
((
item
)
=>
({
value
:
item
.
id
.
toString
(),
label
:
item
.
name
,
children
:
item
.
children
?
convertToTreeData
(
item
.
children
)
:
[],
}));
};
// 查询表单数据
const
searchForm
=
ref
({
name
:
""
,
mobile
:
""
,
});
// 查询表单配置
const
searchConfig
=
{
inline
:
true
,
labelWidth
:
"80px"
,
showButtons
:
true
,
submitText
:
"查询"
,
resetText
:
"重置"
,
};
// 查询表单项配置
const
searchItems
=
[
{
type
:
"input"
,
prop
:
"name"
,
label
:
"菜单名称:"
,
placeholder
:
"请输入菜单名称"
,
clearable
:
true
,
span
:
8
,
},
{
type
:
"input"
,
prop
:
"mobile"
,
label
:
"菜单编码:"
,
placeholder
:
"请输入菜单编码"
,
clearable
:
true
,
span
:
8
,
},
];
// 表格数据
const
tableData
=
ref
([]);
const
total
=
ref
(
0
);
const
currentPage
=
ref
(
1
);
const
pageSize
=
ref
(
10
);
// 表格列配置
const
tableColumns
=
[
{
prop
:
"name"
,
label
:
"菜单名称"
,
width
:
180
,
tree
:
true
,
},
{
prop
:
"code"
,
label
:
"菜单编号"
,
minWidth
:
120
,
},
{
prop
:
"type"
,
label
:
"菜单类型"
,
minWidth
:
100
,
},
{
prop
:
"icon"
,
label
:
"菜单图标"
,
minWidth
:
100
,
},
{
prop
:
"order"
,
label
:
"排序"
,
minWidth
:
80
,
align
:
"center"
,
},
{
prop
:
"createdAt"
,
label
:
"创建时间"
,
width
:
250
,
align
:
"center"
,
},
{
prop
:
"operations"
,
label
:
"操作"
,
width
:
200
,
slot
:
"operations"
,
fixed
:
"right"
,
align
:
"center"
,
},
];
// 对话框相关
const
dialogVisible
=
ref
(
false
);
const
dialogTitle
=
ref
(
"新增菜单"
);
const
isEdit
=
ref
(
false
);
const
editIndex
=
ref
(
-
1
);
// 用户表单数据
const
userForm
=
ref
({
name
:
""
,
departs
:
[],
positions
:
[],
roles
:
[],
enable
:
"0"
,
});
// 用户表单配置
const
formConfig
=
{
labelWidth
:
"100px"
,
showButtons
:
true
,
submitText
:
"保存"
,
resetText
:
"取消"
,
};
// 用户表单项配置
const
formItems
=
computed
(()
=>
[
{
type
:
"select"
,
prop
:
"name"
,
label
:
"父级菜单:"
,
placeholder
:
"请选择顶级菜单"
,
span
:
12
,
required
:
true
,
rules
:
[{
required
:
true
,
message
:
"请选择顶级菜单"
,
trigger
:
"blur"
}],
},
{
type
:
"radio"
,
prop
:
""
,
label
:
"菜单类型:"
,
span
:
12
,
options
:
[
{
label
:
"目录"
,
value
:
"1"
,
},
{
label
:
"菜单"
,
value
:
"0"
,
},
],
},
{
type
:
"input"
,
prop
:
"mobile"
,
label
:
"菜单名称:"
,
placeholder
:
"请输入菜单名称"
,
span
:
12
,
required
:
true
,
rules
:
[{
required
:
true
,
message
:
"请输入菜单名称"
,
trigger
:
"blur"
}],
},
{
type
:
"input"
,
prop
:
""
,
label
:
"菜单编号:"
,
placeholder
:
"请输入菜单编号"
,
span
:
12
,
required
:
true
,
rules
:
[{
required
:
true
,
message
:
"请输入菜单编号"
,
trigger
:
"blur"
}],
},
{
type
:
"input"
,
prop
:
""
,
label
:
"Vue组件:"
,
placeholder
:
"请输入Vue组件"
,
span
:
12
,
},
{
type
:
"input"
,
prop
:
""
,
label
:
"路由名称:"
,
placeholder
:
"请输入路由名称"
,
span
:
12
,
},
{
type
:
"input"
,
prop
:
""
,
label
:
"路由地址:"
,
placeholder
:
"请输入路由地址"
,
span
:
12
,
},
{
type
:
"input"
,
prop
:
""
,
label
:
"排序:"
,
placeholder
:
"请输入排序"
,
span
:
12
,
},
{
type
:
"radio"
,
prop
:
""
,
label
:
"显示状态:"
,
span
:
12
,
options
:
[
{
label
:
"显示"
,
value
:
"0"
},
{
label
:
"隐藏"
,
value
:
"1"
},
],
},
{
type
:
"radio"
,
prop
:
""
,
label
:
"嵌套模式:"
,
span
:
12
,
options
:
[
{
label
:
"是"
,
value
:
"0"
},
{
label
:
"否"
,
value
:
"1"
},
],
},
{
type
:
"upload"
,
prop
:
""
,
label
:
"菜单图标:"
,
span
:
12
,
},
]);
// 表单验证规则
const
formRules
=
{};
// 事件处理函数
const
handleSearch
=
(
formData
)
=>
{
currentPage
.
value
=
1
;
loadTableData
();
};
const
handleReset
=
()
=>
{
searchForm
.
value
=
{
name
:
""
,
mobile
:
""
,
};
currentPage
.
value
=
1
;
loadTableData
();
};
const
handleSizeChange
=
(
size
)
=>
{
pageSize
.
value
=
size
;
currentPage
.
value
=
1
;
loadTableData
();
};
const
handleCurrentPageChange
=
(
page
)
=>
{
currentPage
.
value
=
page
;
loadTableData
();
};
// 新增用户
const
handleAdd
=
()
=>
{
isEdit
.
value
=
false
;
dialogTitle
.
value
=
"新增菜单"
;
userForm
.
value
=
{
name
:
""
,
departs
:
[],
positions
:
[],
roles
:
[],
enable
:
"0"
,
};
dialogVisible
.
value
=
true
;
};
let
currentID
=
ref
();
// 编辑
const
handleEdit
=
(
row
,
index
)
=>
{
isEdit
.
value
=
true
;
dialogTitle
.
value
=
"编辑用户"
;
editIndex
.
value
=
index
;
// proxy.$post({
// url: "/api/user/manage/getUserInfo",
// data: { id: row.id },
// callback: (data) => {
// userForm.value = { ...data };
// currentID.value = data.id;
// },
// error: (err) => {
// ElMessage.error("编辑失败:", err);
// },
// });
dialogVisible
.
value
=
true
;
};
// 删除
const
handleDelete
=
async
(
row
,
index
)
=>
{
try
{
// await ElMessageBox.confirm(`确定要删除用户"${row.name}"吗?`, "提示", {
// confirmButtonText: "确定",
// cancelButtonText: "取消",
// type: "warning",
// });
// proxy.$post({
// url: "/api/user/manage/deleteUser",
// data: { id: row.id },
// callback: (data) => {
// dialogVisible.value = false;
// loadTableData();
// ElMessage.success("删除成功");
// },
// error: (err) => {
// ElMessage.error("删除失败:", err);
// },
// });
// loadTableData();
}
catch
{}
};
const
handleFormSubmit
=
(
formData
)
=>
{
if
(
isEdit
.
value
)
{
// 编辑用户
const
updateUser
=
{
...
formData
,
};
// proxy.$post({
// url: "/api/user/manage/updateUser",
// data: updateUser,
// callback: (data) => {
// dialogVisible.value = false;
// loadTableData();
// ElMessage.success("用户信息更新成功");
// },
// error: (err) => {
// ElMessage.error("用户信息更新失败:", err);
// },
// });
}
else
{
// 新增用户
const
newUser
=
{
...
formData
,
};
// proxy.$post({
// url: "/api/user/manage/createUser",
// data: newUser,
// callback: (data) => {
// dialogVisible.value = false;
// loadTableData();
// ElMessage.success("用户添加成功");
// },
// error: (err) => {
// ElMessage.error("用户添加失败:", err);
// },
// });
}
};
const
handleFormReset
=
()
=>
{
dialogVisible
.
value
=
false
;
};
const
handleDialogClose
=
()
=>
{
dialogVisible
.
value
=
false
;
};
// 表格数据
const
loadTableData
=
()
=>
{
loading
.
value
=
true
;
proxy
.
$post
({
url
:
"/api/user/menu/treeMenu"
,
data
:
{
...
searchForm
.
value
,
page
:
currentPage
.
value
,
pageSize
:
pageSize
.
value
,
},
callback
:
(
data
)
=>
{
tableData
.
value
=
data
;
total
.
value
=
data
.
count
;
loading
.
value
=
false
;
},
error
:
(
err
)
=>
{
loading
.
value
=
false
;
ElMessage
.
error
(
"加载数据失败"
);
},
});
};
onMounted
(()
=>
{
loadTableData
();
});
</
script
>
<
style
scoped
lang=
"less"
>
.user-manage {
padding: 20px;
background: rgba(157, 188, 218, 0.1);
height: 100%;
display: flex;
flex-direction: column;
box-sizing: border-box;
.search-form {
background: rgba(255, 255, 255, 0.9);
border-radius: 8px;
padding: 20px;
margin-bottom: 20px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
flex-shrink: 0;
}
.table-container {
background: rgba(255, 255, 255, 0.9);
border-radius: 8px;
padding: 20px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
}
</
style
>
src/views/systemManage/roleManage.vue
View file @
1d2b693a
...
...
@@ -11,7 +11,9 @@
</div>
<div
class=
"table-container"
>
<common-table
:tableHeight=
"tableHeight"
:autoHeight=
"true"
:maxRows=
"10"
:rowHeight=
"40"
:data=
"tableData"
:columns=
"tableColumns"
:total=
"total"
...
...
@@ -32,10 +34,7 @@
<el-button
type=
"text"
size=
"small"
@
click=
"handleDelete(row, index)"
>
删除
</el-button>
<el-button
type=
"text"
size=
"small"
@
click=
"handleMenu(row, index)"
>
菜单配置
</el-button
>
<el-button
type=
"text"
size=
"small"
>
数据权限
</el-button>
<!--
<el-button
type=
"text"
size=
"small"
>
数据权限
</el-button>
-->
</
template
>
</common-table>
</div>
...
...
@@ -47,7 +46,7 @@
@
close=
"handleDialogClose"
>
<commonForm
v-model=
"
user
Form"
v-model=
"
role
Form"
:config=
"formConfig"
:items=
"formItems"
:rules=
"formRules"
...
...
@@ -55,7 +54,7 @@
@
reset=
"handleFormReset"
/>
</el-dialog>
<el-dialog
v-model=
"menuVisible"
title=
"菜单配置"
>
<
!-- <
el-dialog v-model="menuVisible" title="菜单配置">
<el-tree
:data="treeData"
show-checkbox
...
...
@@ -63,13 +62,14 @@
node-key="id"
ref="tree"
highlight-current
@node-click="handleNodeClick"
>
</el-tree>
<
template
#
footer
>
<template #footer>
<el-button type="primary" @click="hanldeSubmit">保存</el-button>
<el-button>取消</el-button>
</template>
</el-dialog>
</el-dialog>
-->
</div>
</template>
...
...
@@ -84,22 +84,12 @@ import { da } from "element-plus/es/locales.mjs";
const
{
proxy
}
=
getCurrentInstance
();
const
loading
=
ref
(
false
);
const
treeData
=
ref
([]);
// 计算表格高度
const
tableHeight
=
computed
(()
=>
{
const
headerHeight
=
50
;
const
paginationHeight
=
50
;
const
rowHeight
=
40
;
const
baseHeight
=
headerHeight
+
paginationHeight
;
const
maxRows
=
Math
.
min
(
tableData
.
value
.
length
,
10
);
const
contentHeight
=
maxRows
*
rowHeight
;
return
`
${
baseHeight
+
contentHeight
}
px`
;
});
const
tree
=
ref
(
null
);
// 数据转换函数
const
convertToTreeData
=
(
apiData
)
=>
{
return
apiData
.
map
((
item
)
=>
({
id
:
item
.
id
,
value
:
item
.
id
.
toString
()
,
label
:
item
.
name
,
children
:
item
.
children
?
convertToTreeData
(
item
.
children
)
:
[],
}));
...
...
@@ -167,16 +157,14 @@ const tableColumns = [
// 对话框相关
const
dialogVisible
=
ref
(
false
);
const
menuVisible
=
ref
(
false
);
const
dialogTitle
=
ref
(
"新增角色"
);
const
isEdit
=
ref
(
false
);
const
editIndex
=
ref
(
-
1
);
// 用户表单数据
const
user
Form
=
ref
({
const
role
Form
=
ref
({
name
:
""
,
createdAt
:
""
,
updatedAt
:
""
,
menus
:
[],
});
// 用户表单配置
...
...
@@ -199,17 +187,19 @@ const formItems = computed(() => [
rules
:
[{
required
:
true
,
message
:
"请输入角色名称"
,
trigger
:
"blur"
}],
},
{
type
:
"date"
,
prop
:
"createdAt"
,
label
:
"创建时间"
,
placeholder
:
"请输入创建时间"
,
span
:
24
,
},
{
type
:
"date"
,
prop
:
"updatedAt"
,
label
:
"更新时间"
,
placeholder
:
"请输入更新时间"
,
type
:
"tree"
,
prop
:
"menus"
,
label
:
"菜单配置"
,
placeholder
:
"请选择菜单配置"
,
data
:
treeData
.
value
,
clearable
:
true
,
filterable
:
true
,
checkStrictly
:
true
,
renderAfterExpand
:
false
,
showCheckbox
:
false
,
multiple
:
true
,
collapseTags
:
true
,
maxCollapseTags
:
2
,
span
:
24
,
},
]);
...
...
@@ -243,28 +233,35 @@ const handleCurrentPageChange = (page) => {
loadTableData
();
};
// 树节点点击
const
handleNodeClick
=
(
data
,
node
,
element
)
=>
{
// console.log(data, "data");
// console.log(node, "node");
// console.log(element, "element");
};
// 新增用户
const
handleAdd
=
()
=>
{
isEdit
.
value
=
false
;
dialogTitle
.
value
=
"新增用户"
;
user
Form
.
value
=
{
role
Form
.
value
=
{
name
:
""
,
createdAt
:
""
,
updatedAt
:
""
,
menus
:
[],
};
dialogVisible
.
value
=
true
;
};
let
currentID
=
ref
();
let
currentRow
=
ref
();
// 编辑
const
handleEdit
=
(
row
,
index
)
=>
{
isEdit
.
value
=
true
;
dialogTitle
.
value
=
"编辑用户"
;
editIndex
.
value
=
index
;
currentRow
.
value
=
row
;
proxy
.
$post
({
url
:
"/api/user/
manage/getUserInfo
"
,
url
:
"/api/user/
role/getRole
"
,
data
:
{
id
:
row
.
id
},
callback
:
(
data
)
=>
{
user
Form
.
value
=
{
...
data
};
role
Form
.
value
=
{
...
data
};
currentID
.
value
=
data
.
id
;
},
error
:
(
err
)
=>
{
...
...
@@ -297,10 +294,6 @@ const handleDelete = async (row, index) => {
loadTableData
();
}
catch
{}
};
// 菜单配置
const
handleMenu
=
()
=>
{
menuVisible
.
value
=
true
;
};
const
handleFormSubmit
=
(
formData
)
=>
{
if
(
isEdit
.
value
)
{
...
...
@@ -308,6 +301,7 @@ const handleFormSubmit = (formData) => {
const
updateUser
=
{
...
formData
,
id
:
currentID
.
value
,
menus
:
Array
.
isArray
(
formData
.
menus
)
?
formData
.
menus
:
[],
};
proxy
.
$post
({
url
:
"/api/user/role/updateRole"
,
...
...
@@ -315,10 +309,10 @@ const handleFormSubmit = (formData) => {
callback
:
(
data
)
=>
{
dialogVisible
.
value
=
false
;
loadTableData
();
ElMessage
.
success
(
"
用户信息
更新成功"
);
ElMessage
.
success
(
"更新成功"
);
},
error
:
(
err
)
=>
{
ElMessage
.
error
(
"
用户信息
更新失败:"
,
err
);
ElMessage
.
error
(
"更新失败:"
,
err
);
},
});
}
else
{
...
...
@@ -350,7 +344,18 @@ const handleDialogClose = () => {
};
const
hanldeSubmit
=
()
=>
{
menuVisible
.
value
=
false
;
// 获取当前复选框选中的节点信息
const
checkedNodes
=
tree
.
value
?.
getCheckedNodes
();
const
halfCheckedNodes
=
tree
.
value
?.
getHalfCheckedNodes
();
// 获取选中节点的ID
const
checkedIds
=
checkedNodes
?
checkedNodes
.
map
((
node
)
=>
node
.
id
)
:
[];
const
halfCheckedIds
=
halfCheckedNodes
?
halfCheckedNodes
.
map
((
node
)
=>
node
.
id
)
:
[];
// 合并所有选中的节点ID(完全选中和半选中的)
const
allSelectedIds
=
[...
checkedIds
,
...
halfCheckedIds
];
};
// 表格数据
const
loadTableData
=
()
=>
{
...
...
@@ -382,7 +387,6 @@ const handleTreeData = () => {
pageSize
:
pageSize
.
value
,
},
callback
:
(
data
)
=>
{
console
.
log
(
data
,
"234234"
);
treeData
.
value
=
convertToTreeData
(
data
);
},
error
:
(
err
)
=>
{
...
...
@@ -422,4 +426,29 @@ onMounted(() => {
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
}
.el-tree {
max-height: 500px;
overflow-y: auto;
&:not(:hover) {
scrollbar-width: none;
-ms-overflow-style: none;
&::-webkit-scrollbar {
display: none;
}
}
&:hover {
scrollbar-width: thin;
&::-webkit-scrollbar {
display: block;
width: 6px;
}
&::-webkit-scrollbar-thumb {
background-color: rgba(144, 147, 153, 0.3);
border-radius: 3px;
}
&::-webkit-scrollbar-track {
background-color: transparent;
}
}
}
</
style
>
src/views/systemManage/userManage.vue
View file @
1d2b693a
...
...
@@ -11,7 +11,9 @@
</div>
<div
class=
"table-container"
>
<common-table
:tableHeight=
"tableHeight"
:autoHeight=
"true"
:maxRows=
"10"
:rowHeight=
"40"
:data=
"tableData"
:columns=
"tableColumns"
:total=
"total"
...
...
@@ -78,18 +80,7 @@ import { da } from "element-plus/es/locales.mjs";
const
{
proxy
}
=
getCurrentInstance
();
const
loading
=
ref
(
false
);
// 计算表格高度
const
tableHeight
=
computed
(()
=>
{
const
headerHeight
=
50
;
const
paginationHeight
=
50
;
const
rowHeight
=
40
;
const
baseHeight
=
headerHeight
+
paginationHeight
;
// 1.如果数据超过10条,固定显示10行的高度 + 滚动条;2.如果数据不超过10条,按实际行数计算高度
const
maxRows
=
Math
.
min
(
tableData
.
value
.
length
,
10
);
const
contentHeight
=
maxRows
*
rowHeight
;
return
`
${
baseHeight
+
contentHeight
}
px`
;
});
// 数据转换函数
const
convertToTreeData
=
(
apiData
)
=>
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment