From 2cf4225d7748322520d5374c92796a23d9517fe1 Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期四, 26 二月 2026 10:29:03 +0800
Subject: [PATCH] 湟水峡 1.人员模块代码迁移
---
src/api/personnelManagement/attendanceRules.js | 45
src/views/personnelManagement/payrollManagement/components/formDia.vue | 14
src/views/personnelManagement/payrollManagement/index.vue | 1
src/views/personnelManagement/scheduling/index.vue | 10
src/views/personnelManagement/attendanceCheckin/index.vue | 507 +++++++
src/views/personnelManagement/contractManagement/index.vue | 20
src/views/personnelManagement/attendanceCheckin/checkinRules/components/form.vue | 496 +++++++
src/views/personnelManagement/selfService/index.vue | 12
src/api/personnelManagement/staffAnalytics.js | 26
src/views/personnelManagement/contractManagement/components/formDia.vue | 40
src/views/personnelManagement/employeeRecord/components/RenewContract.vue | 141 ++
src/views/personnelManagement/analytics/index.vue | 228 +-
src/views/personnelManagement/employeeRecord/index.vue | 82 +
src/views/personnelManagement/monthlyStatistics/components/formDia.vue | 318 ++++
src/api/personnelManagement/monthlyStatistics.js | 65 +
src/views/personnelManagement/employeeRecord/components/Show.vue | 73 +
/dev/null | 280 ----
src/views/personnelManagement/dimission/components/formDia.vue | 425 ++---
src/views/personnelManagement/employeeRecord/components/NewOrEditFormDia.vue | 373 +++++
src/api/personnelManagement/staffOnJob.js | 9
src/views/personnelManagement/attendanceCheckin/checkinRules/index.vue | 293 ++++
src/api/personnelManagement/personalAttendanceRecords.js | 25
src/views/personnelManagement/contractManagement/filesDia.vue | 13
src/views/personnelManagement/dimission/index.vue | 60
src/views/personnelManagement/monthlyStatistics/index.vue | 303 ++++
25 files changed, 3,121 insertions(+), 738 deletions(-)
diff --git a/src/api/personnelManagement/attendanceRules.js b/src/api/personnelManagement/attendanceRules.js
new file mode 100644
index 0000000..021442e
--- /dev/null
+++ b/src/api/personnelManagement/attendanceRules.js
@@ -0,0 +1,45 @@
+import request from "@/utils/request";
+
+// 鑾峰彇鎵撳崱瑙勫垯鍒楄〃
+export function getAttendanceRules(query) {
+ return request({
+ url: "/personalAttendanceLocationConfig/listPage",
+ method: "get",
+ params: query,
+ });
+}
+
+// 鏂板鎵撳崱瑙勫垯
+export function addAttendanceRule(data) {
+ return request({
+ url: "/personalAttendanceLocationConfig/add",
+ method: "post",
+ data,
+ });
+}
+
+// 鏇存柊鎵撳崱瑙勫垯
+export function updateAttendanceRule(data) {
+ return request({
+ url: "/attendanceRules/update",
+ method: "put",
+ data,
+ });
+}
+
+// 鍒犻櫎鎵撳崱瑙勫垯
+export function deleteAttendanceRule(ids) {
+ return request({
+ url: `/personalAttendanceLocationConfig/del`,
+ method: "delete",
+ data: ids,
+ });
+}
+
+// 鑾峰彇鍗曚釜鎵撳崱瑙勫垯璇︽儏
+export function getAttendanceRuleDetail(id) {
+ return request({
+ url: `/attendanceRules/detail/${id}`,
+ method: "get",
+ });
+}
diff --git a/src/api/personnelManagement/monthlyStatistics.js b/src/api/personnelManagement/monthlyStatistics.js
new file mode 100644
index 0000000..a070d0f
--- /dev/null
+++ b/src/api/personnelManagement/monthlyStatistics.js
@@ -0,0 +1,65 @@
+import request from "@/utils/request";
+
+// 浜哄憳钖祫鍙拌处鍒楄〃
+export function monthlyStatisticsListPage(query) {
+ return request({
+ url: "/compensationPerformance/listPage",
+ method: "get",
+ params: query,
+ });
+}
+
+// 浜哄憳钖祫鍙拌处璇︽儏
+export function monthlyStatisticsGet(id) {
+ return request({
+ url: "/monthlyStatistics/get",
+ method: "get",
+ params: { id },
+ });
+}
+
+// 鏂板浜哄憳钖祫鍙拌处
+export function monthlyStatisticsAdd(data) {
+ return request({
+ url: "/compensationPerformance/add",
+ method: "post",
+ data,
+ });
+}
+
+// 缂栬緫浜哄憳钖祫鍙拌处
+export function monthlyStatisticsUpdate(data) {
+ return request({
+ url: "/compensationPerformance/update",
+ method: "post",
+ data,
+ });
+}
+
+// 鍒犻櫎浜哄憳钖祫鍙拌处
+export function monthlyStatisticsDelete(ids) {
+ return request({
+ url: "/compensationPerformance/delete",
+ method: "delete",
+ data: ids,
+ });
+}
+
+// 瀵煎嚭浜哄憳钖祫鍙拌处
+export function monthlyStatisticsExport(query) {
+ return request({
+ url: "/compensationPerformance/export",
+ method: "get",
+ params: query,
+ responseType: "blob",
+ });
+}
+
+// 浜哄憳鍒楄〃
+export function staffOnJobList(query) {
+ return request({
+ url: "/staff/staffOnJob/list",
+ method: "get",
+ params: query,
+ });
+}
diff --git a/src/api/personnelManagement/onboarding.js b/src/api/personnelManagement/onboarding.js
deleted file mode 100644
index 39dbf22..0000000
--- a/src/api/personnelManagement/onboarding.js
+++ /dev/null
@@ -1,49 +0,0 @@
-import request from "@/utils/request";
-
-// 鏌ヨ浜哄憳鍏ヨ亴鍒楄〃
-export function staffJoinListPage(query) {
- return request({
- url: "/staff/staffJoinLeaveRecord/listPage",
- method: "get",
- params: query,
- });
-}
-// 鏂板浜哄憳鍏ヨ亴
-export function staffJoinAdd(query) {
- return request({
- url: "/staff/staffJoinLeaveRecord/add",
- method: "post",
- data: query,
- });
-}
-// 淇敼浜哄憳鍏ヨ亴
-export function staffJoinUpdate(query) {
- return request({
- url: "/staff/staffJoinLeaveRecord/update",
- method: "post",
- data: query,
- });
-}
-// 鏌ヨ鍛樺伐鍏ヨ亴淇℃伅
-export function getStaffJoinInfo(query) {
- return request({
- url: "/staff/staffJoinLeaveRecord/" + query,
- method: "get",
- data: query,
- });
-}
-// 鍒犻櫎鍛樺伐
-export function staffJoinDel(query) {
- return request({
- url: "/staff/staffJoinLeaveRecord/del",
- method: "delete",
- data: query,
- });
-}
-
-export function getStaffOnJob() {
- return request({
- url: "/staff/staffOnJob/list",
- method: "get",
- });
-}
diff --git a/src/api/personnelManagement/personalAttendanceRecords.js b/src/api/personnelManagement/personalAttendanceRecords.js
new file mode 100644
index 0000000..bdd9e1c
--- /dev/null
+++ b/src/api/personnelManagement/personalAttendanceRecords.js
@@ -0,0 +1,25 @@
+import request from "@/utils/request.js";
+
+export function createPersonalAttendanceRecord(params) {
+ return request({
+ url: "/personalAttendanceRecords",
+ method: "post",
+ data: params,
+ });
+}
+
+export function findPersonalAttendanceRecords(query) {
+ return request({
+ url: "/personalAttendanceRecords/listPage",
+ method: "get",
+ params: query,
+ });
+}
+
+export function findTodayPersonalAttendanceRecord(query) {
+ return request({
+ url: "/personalAttendanceRecords/today",
+ method: "get",
+ params: query,
+ });
+}
\ No newline at end of file
diff --git a/src/api/personnelManagement/staffAnalytics.js b/src/api/personnelManagement/staffAnalytics.js
new file mode 100644
index 0000000..83eb375
--- /dev/null
+++ b/src/api/personnelManagement/staffAnalytics.js
@@ -0,0 +1,26 @@
+import request from "@/utils/request.js";
+
+// 绂昏亴鍘熷洜鍒嗘瀽
+export function findStaffLeaveReasonAnalysis() {
+ return request({
+ url: "/staff/analytics/reason",
+ method: "get"
+ });
+}
+
+// 12涓湀鍛樺伐娴佸姩娴佸け鐜囧垎鏋�
+export function findStaffAnalysisMonthlyTurnoverRateFor12Months() {
+ return request({
+ url: "/staff/analytics/monthly_turnover_rate",
+ method: "get"
+ });
+}
+
+export function findStaffAnalysisTotalStatistic() {
+ return request({
+ url: "/staff/analytics/total_statistic",
+ method: "get"
+ });
+}
+
+
diff --git a/src/api/personnelManagement/staffOnJob.js b/src/api/personnelManagement/staffOnJob.js
index 7da5469..7a14391 100644
--- a/src/api/personnelManagement/staffOnJob.js
+++ b/src/api/personnelManagement/staffOnJob.js
@@ -17,6 +17,15 @@
})
}
+// 鏌ヨ鍛樺伐鍏ヨ亴淇℃伅
+export function getStaffOnJobInfoByUserName(query) {
+ return request({
+ url: '/staff/staffOnJob/byUserName',
+ method: 'get',
+ params: query,
+ })
+}
+
// 鏂板鍛樺伐
export function createStaffOnJob(params) {
return request({
diff --git a/src/views/personnelManagement/analytics/index.vue b/src/views/personnelManagement/analytics/index.vue
index 2bca335..9e6e449 100644
--- a/src/views/personnelManagement/analytics/index.vue
+++ b/src/views/personnelManagement/analytics/index.vue
@@ -1,5 +1,5 @@
<template>
- <div class="app-container analytics-container">
+ <div class="app-container analytics-container" v-loading="loading">
<!-- 鍏抽敭鎸囨爣鍗$墖 -->
<el-row :gutter="20" class="metrics-cards">
@@ -11,18 +11,18 @@
<component :is="item.icon" />
</el-icon>
</div>
- <div class="card-info">
+ <div class="card-info">
<div class="card-number">
<el-skeleton-item v-if="loading" variant="text" style="width: 60px; height: 32px;" />
<span v-else>{{ item.value }}{{ item.unit }}</span>
</div>
<div class="card-label">{{ item.label }}</div>
- <div class="card-trend" :class="item.trend > 0 ? 'positive' : 'negative'" v-if="item.showTrend !== false">
- <el-icon>
- <component :is="item.trend > 0 ? 'ArrowUp' : 'ArrowDown'" />
- </el-icon>
- {{ Math.abs(item.trend) }}%
- </div>
+<!-- <div class="card-trend" :class="item.trend > 0 ? 'positive' : 'negative'" v-if="item.showTrend !== false">-->
+<!-- <el-icon>-->
+<!-- <component :is="item.trend > 0 ? 'ArrowUp' : 'ArrowDown'" />-->
+<!-- </el-icon>-->
+<!-- {{ Math.abs(item.trend) }}%-->
+<!-- </div>-->
</div>
</div>
</el-card>
@@ -64,21 +64,6 @@
<!-- 绗簩琛屽浘琛� -->
<el-row :gutter="20" class="charts-section">
- <!-- 缂栧埗杈炬垚鐜� -->
- <el-col :span="12">
- <el-card class="chart-card">
- <template #header>
- <div class="card-header">
- <span>缂栧埗杈炬垚鐜�</span>
- <el-tag type="warning">鍚勯儴闂ㄥ姣�</el-tag>
- </div>
- </template>
- <div class="chart-container">
- <div ref="staffingChartRef" class="chart"></div>
- </div>
- </el-card>
- </el-col>
-
<!-- 鍛樺伐娴佸け鍘熷洜鍒嗘瀽 -->
<el-col :span="12">
<el-card class="chart-card">
@@ -98,19 +83,15 @@
</template>
<script setup>
-import { ref, reactive, onMounted, onUnmounted } from 'vue'
+import { ref, onMounted, onUnmounted, nextTick } from 'vue'
import { ElMessage } from 'element-plus'
-import {
- Refresh,
- User,
- TrendCharts,
- DataAnalysis,
- PieChart,
- ArrowUp,
- ArrowDown
-} from '@element-plus/icons-vue'
import * as echarts from 'echarts'
-import { staffOnJobListPage } from '@/api/personnelManagement/employeeRecord.js'
+import {listDept} from "@/api/system/dept.js";
+import {
+ findStaffAnalysisMonthlyTurnoverRateFor12Months,
+ findStaffLeaveReasonAnalysis,
+ findStaffAnalysisTotalStatistic
+} from "@/api/personnelManagement/staffAnalytics.js";
// 鍝嶅簲寮忔暟鎹�
const loading = ref(false)
@@ -151,14 +132,6 @@
trend: 0
},
{
- label: '缂栧埗杈炬垚鐜�',
- value: 0,
- unit: '%',
- icon: 'DataAnalysis',
- type: 'success',
- trend: 0
- },
- {
label: '鍦ㄨ亴鍛樺伐鏁�',
value: 0,
unit: '浜�',
@@ -171,16 +144,56 @@
// 閮ㄩ棬鏁版嵁
const departmentData = ref([])
+// 鍛樺伐娴佸け鍘熷洜鍒嗘瀽鏁版嵁
+const staffLeaveReasons = ref([])
+// 12涓湀鍛樺伐娴佸姩娴佸け鐜囧垎鏋愭暟鎹�
+const turnoverRateStatistics = ref([])
-// 鑾峰彇鍦ㄨ亴鍛樺伐鏁�
-const getStaffCount = async () => {
+// 鑾峰彇閮ㄩ棬鏁版嵁
+const getDepartmentData = async () => {
try {
- const res = await staffOnJobListPage({ staffState: 1, current: 1, size: 1 })
+ const res = await listDept()
if (res && res.data) {
- keyMetrics.value[3].value = res.data.total || 0
+ departmentData.value = res.data
}
} catch (error) {
- console.error('鑾峰彇鍦ㄨ亴鍛樺伐鏁板け璐�:', error)
+ console.error('鑾峰彇閮ㄩ棬鏁版嵁澶辫触:', error)
+ }
+}
+
+const getStaffLeaveReasonAnalysis = async () => {
+ try {
+ const res = await findStaffLeaveReasonAnalysis()
+ if (res && res.data) {
+ staffLeaveReasons.value = res.data || []
+ }
+ } catch (error) {
+ console.error('鑾峰彇鍛樺伐娴佸け鍘熷洜鍒嗘瀽澶辫触:', error)
+ }
+}
+
+// 淇敼涓鸿繑鍥濸romise鐨勫紓姝ュ嚱鏁�
+const getMonthlyTurnoverRateFor12Months = async () => {
+ try {
+ const res = await findStaffAnalysisMonthlyTurnoverRateFor12Months()
+ if (res && res.data) {
+ turnoverRateStatistics.value = res.data || []
+ }
+ } catch (error) {
+ console.error('鑾峰彇12涓湀鍛樺伐娴佸姩娴佸け鐜囧垎鏋愭暟鎹け璐�:', error)
+ }
+}
+
+const getStaffAnalysisTotalStatistic = async () => {
+ try {
+ const res = await findStaffAnalysisTotalStatistic()
+ if (res && res.data) {
+ keyMetrics.value[0].value = res.data.totalFlowRate || 0
+ keyMetrics.value[1].value = res.data.totalTurnoverRate || 0
+ keyMetrics.value[2].value = res.data.currentOnJobCount || 0
+ }
+ } catch (error) {
+ console.error('鑾峰彇鍛樺伐鍒嗘瀽鎬荤粺璁℃暟鎹け璐�:', error)
}
}
@@ -213,49 +226,28 @@
}
}
-// 鐢熸垚妯℃嫙鏁版嵁
-const generateMockData = () => {
- // 鐢熸垚鍏抽敭鎸囨爣鏁版嵁
- keyMetrics.value[0].value = (Math.random() * 5 + 2).toFixed(1)
- keyMetrics.value[0].trend = (Math.random() * 3 - 1.5).toFixed(1)
-
- keyMetrics.value[1].value = (Math.random() * 3 + 1).toFixed(1)
- keyMetrics.value[1].trend = (Math.random() * 2 - 1).toFixed(1)
-
- keyMetrics.value[2].value = (Math.random() * 15 + 85).toFixed(1)
- keyMetrics.value[2].trend = (Math.random() * 3 - 1.5).toFixed(1)
-
- // 鐢熸垚閮ㄩ棬鏁版嵁
- const departments = ['鎶�鏈儴', '閿�鍞儴', '浜轰簨閮�', '璐㈠姟閮�', '鐢熶骇閮�', '甯傚満閮�']
- departmentData.value = departments.map(dept => ({
- department: dept,
- currentStaff: Math.floor(Math.random() * 30 + 20),
- plannedStaff: Math.floor(Math.random() * 10 + 35),
- staffingRate: Math.floor(Math.random() * 20 + 80),
- turnoverRate: (Math.random() * 4 + 1).toFixed(1),
- attritionRate: (Math.random() * 2 + 0.5).toFixed(1),
- newHires: Math.floor(Math.random() * 5 + 1),
- resignations: Math.floor(Math.random() * 3 + 1),
- status: Math.random() > 0.7 ? '寮傚父' : '姝e父'
- }))
-}
-
-// 鍒锋柊鏁版嵁
+// 淇敼涓哄紓姝ュ嚱鏁帮紝纭繚鏁版嵁鍔犺浇瀹屾垚鍚庡啀娓叉煋鍥捐〃
const refreshData = async () => {
- loading.value = true
try {
- // 妯℃嫙API璋冪敤寤惰繜
- await new Promise(resolve => setTimeout(resolve, 500))
-
- generateMockData()
+ loading.value = true
+
+ // 绛夊緟鎵�鏈夋暟鎹姞杞藉畬鎴�
+ await Promise.all([
+ getDepartmentData(),
+ getStaffLeaveReasonAnalysis(),
+ getMonthlyTurnoverRateFor12Months(),
+ getStaffAnalysisTotalStatistic()
+ ])
+
+ await nextTick()
renderAllCharts()
-
+
if (!autoRefreshEnabled.value) {
ElMessage.success('鏁版嵁鍒锋柊鎴愬姛')
}
} catch (error) {
- console.error('鍒锋柊鏁版嵁澶辫触:', error)
- ElMessage.error('鍒锋柊鏁版嵁澶辫触')
+ console.error('鏁版嵁鍒锋柊澶辫触:', error)
+ ElMessage.error('鏁版嵁鍒锋柊澶辫触')
} finally {
loading.value = false
}
@@ -276,8 +268,9 @@
if (attritionChartRef.value) {
attritionChart = echarts.init(attritionChartRef.value)
}
-
- renderAllCharts()
+
+ // 鍒濆鍖栨椂涔熷厛鍔犺浇鏁版嵁鍐嶆覆鏌撳浘琛�
+ refreshData()
}, 300)
}
@@ -289,14 +282,15 @@
renderAttritionChart()
}
-// 娓叉煋鍛樺伐娴佸姩鐜囪秼鍔垮浘
+// 淇敼涓轰娇鐢ˋPI杩斿洖鐨勫疄闄呮暟鎹�
const renderTurnoverChart = () => {
if (!turnoverChart) return
-
- const months = ['1鏈�', '2鏈�', '3鏈�', '4鏈�', '5鏈�', '6鏈�', '7鏈�', '8鏈�', '9鏈�', '10鏈�', '11鏈�', '12鏈�']
- const turnoverData = months.map(() => (Math.random() * 5 + 2).toFixed(1))
- const attritionData = months.map(() => (Math.random() * 3 + 1).toFixed(1))
-
+
+ // 浣跨敤API杩斿洖鐨勫疄闄呮暟鎹�
+ const months = turnoverRateStatistics.value.map(item => item.month)
+ const turnoverData = turnoverRateStatistics.value.map(item => item.flowRate || 0)
+ const attritionData = turnoverRateStatistics.value.map(item => item.turnoverRate || 0)
+
const option = {
title: {
text: '鍛樺伐娴佸姩鐜囪秼鍔�',
@@ -346,19 +340,19 @@
}
]
}
-
+
turnoverChart.setOption(option)
}
// 娓叉煋閮ㄩ棬浜哄憳鍒嗗竷鍥�
const renderDepartmentChart = () => {
if (!departmentChart) return
-
+
const data = departmentData.value.map(item => ({
- name: item.department,
- value: item.currentStaff
+ name: item.deptName,
+ value: item.staffCount
}))
-
+
const option = {
title: {
text: '閮ㄩ棬浜哄憳鍒嗗竷',
@@ -391,17 +385,17 @@
}
]
}
-
+
departmentChart.setOption(option)
}
// 娓叉煋缂栧埗杈炬垚鐜囧浘
const renderStaffingChart = () => {
if (!staffingChart) return
-
- const departments = departmentData.value.map(item => item.department)
+
+ const departments = departmentData.value.map(item => item.deptName)
const rates = departmentData.value.map(item => item.staffingRate)
-
+
const option = {
title: {
text: '缂栧埗杈炬垚鐜�',
@@ -445,17 +439,17 @@
}
]
}
-
+
staffingChart.setOption(option)
}
// 娓叉煋鍛樺伐娴佸け鍘熷洜鍒嗘瀽鍥�
const renderAttritionChart = () => {
if (!attritionChart) return
-
- const reasons = ['钖祫寰呴亣', '鑱屼笟鍙戝睍', '宸ヤ綔鐜', '涓汉鍘熷洜', '鍏朵粬']
- const data = reasons.map(() => Math.floor(Math.random() * 20 + 5))
-
+
+ const reasons = staffLeaveReasons.value.map(item => item.reasonText)
+ const data = staffLeaveReasons.value.map(item => item.count)
+
const option = {
title: {
text: '鍛樺伐娴佸け鍘熷洜鍒嗘瀽',
@@ -491,14 +485,12 @@
}
]
}
-
+
attritionChart.setOption(option)
}
-
+
// 鐢熷懡鍛ㄦ湡
onMounted(() => {
- generateMockData()
- getStaffCount()
initCharts()
startAutoRefresh()
})
@@ -663,32 +655,32 @@
.analytics-container {
padding: 10px;
}
-
+
.page-header {
padding: 15px;
}
-
+
.page-header h2 {
font-size: 24px;
}
-
+
.header-controls {
flex-direction: column;
gap: 15px;
}
-
+
.refresh-btn {
margin-left: 0;
}
-
+
.metrics-cards .el-col {
margin-bottom: 15px;
}
-
+
.charts-section .el-col {
margin-bottom: 20px;
}
-
+
.chart-container {
height: 300px;
}
@@ -698,11 +690,11 @@
.page-header h2 {
font-size: 20px;
}
-
+
.card-number {
font-size: 24px;
}
-
+
.chart-container {
height: 250px;
}
diff --git a/src/views/personnelManagement/attendanceCheckin/checkinRules/components/form.vue b/src/views/personnelManagement/attendanceCheckin/checkinRules/components/form.vue
new file mode 100644
index 0000000..11e21bc
--- /dev/null
+++ b/src/views/personnelManagement/attendanceCheckin/checkinRules/components/form.vue
@@ -0,0 +1,496 @@
+<template>
+ <el-dialog v-model="dialogVisible"
+ :title="dialogTitle"
+ width="700px"
+ :close-on-click-modal="false">
+ <el-form ref="formRef"
+ :model="form"
+ :rules="rules"
+ label-width="120px"
+ class="mt8">
+ <!-- 閮ㄩ棬閫夋嫨 -->
+ <el-form-item label="閮ㄩ棬"
+ prop="sysDeptId">
+ <el-tree-select v-model="form.sysDeptId"
+ :data="deptOptions"
+ :props="{ value: 'id', label: 'label', children: 'children' }"
+ value-key="id"
+ placeholder="璇烽�夋嫨閮ㄩ棬"
+ check-strictly
+ style="width: 100%"
+ :disabled="['edit', 'view'].includes(operationType)" />
+ </el-form-item>
+ <!-- 鍦扮偣淇℃伅 -->
+ <!-- <el-form-item label="鍦扮偣鍚嶇О"
+ prop="locationName">
+ <el-input v-model="form.locationName"
+ placeholder="璇疯緭鍏ュ湴鐐瑰悕绉�"
+ :disabled="operationType === 'view'" />
+ </el-form-item> -->
+ <!-- 鎵撳崱鑼冨洿 -->
+ <el-form-item label="鎵撳崱鑼冨洿(m)"
+ prop="radius">
+ <el-input-number v-model="form.radius"
+ :min="10"
+ :max="1000"
+ :step="10"
+ placeholder="璇疯緭鍏ユ墦鍗¤寖鍥�"
+ :disabled="operationType === 'view'" />
+ </el-form-item>
+ <!-- 楂樺痉鍦板浘閫夋嫨 -->
+ <el-form-item label="鎵撳崱浣嶇疆"
+ prop="longitude">
+ <div class="map-container">
+ <div class="map-header"
+ style="margin-bottom: 10px">
+ <!-- <el-button @click="getCurrentLocation">
+ <el-icon>
+ <Position />
+ </el-icon>
+ 褰撳墠浣嶇疆
+ </el-button> -->
+ <!-- <span style="margin-left: 10px; color: #909399;font-size: 12px;">鐐瑰嚮鍦板浘閫夋嫨浣嶇疆</span> -->
+ </div>
+ <div id="map-container"
+ class="map"
+ ref="mapContainer"></div>
+ <div class="coordinates-info mt10">
+ <el-input v-model="form.longitude"
+ readonly
+ placeholder="缁忓害"
+ style="width: 140px; margin-right: 10px" />
+ <el-input v-model="form.latitude"
+ readonly
+ placeholder="绾害"
+ style="width: 140px; margin-right: 10px" />
+ <!-- <el-input v-model="form.locationName"
+ placeholder="鍦扮偣鍚嶇О"
+ style="width: calc(100% - 290px)" /> -->
+ </div>
+ </div>
+ </el-form-item>
+ <el-form-item label="鍦扮偣鍚嶇О"
+ prop="locationName">
+ <el-input v-model="form.locationName"
+ :disabled="operationType === 'view'"
+ placeholder="璇疯緭鍏ュ湴鐐瑰悕绉�" />
+ </el-form-item>
+ <!-- 涓婁笅鐝椂闂� -->
+ <el-form-item label="涓婄彮鏃堕棿"
+ prop="startAt">
+ <el-time-picker v-model="form.startAt"
+ format="HH:mm"
+ value-format="HH:mm"
+ placeholder="璇烽�夋嫨涓婄彮鏃堕棿"
+ :disabled="operationType === 'view'" />
+ </el-form-item>
+ <el-form-item label="涓嬬彮鏃堕棿"
+ prop="endAt">
+ <el-time-picker v-model="form.endAt"
+ format="HH:mm"
+ value-format="HH:mm"
+ :picker-options="{
+ minTime: form.startAt
+ }"
+ placeholder="璇烽�夋嫨涓嬬彮鏃堕棿"
+ :disabled="operationType === 'view'" />
+ </el-form-item>
+ </el-form>
+ <template #footer>
+ <span class="dialog-footer">
+ <el-button @click="dialogVisible = false">鍙栨秷</el-button>
+ <el-button type="primary"
+ @click="submitForm"
+ v-if="operationType !== 'view'">
+ 纭畾
+ </el-button>
+ </span>
+ </template>
+ </el-dialog>
+</template>
+
+<script setup>
+ import { ref, reactive, computed, watch, onMounted, nextTick } from "vue";
+ import { ElMessage } from "element-plus";
+ import { Position } from "@element-plus/icons-vue";
+ import { deptTreeSelect } from "@/api/system/user.js";
+ import { addAttendanceRule } from "@/api/personnelManagement/attendanceRules.js";
+
+ const props = defineProps({
+ modelValue: {
+ type: Boolean,
+ default: false,
+ },
+ operationType: {
+ type: String,
+ default: "add",
+ },
+ row: {
+ type: Object,
+ default: () => ({}),
+ },
+ });
+ // const pickerOptions = ref({ minTime: form.value.startAt });
+
+ const emit = defineEmits(["update:modelValue", "close"]);
+
+ const dialogVisible = computed({
+ get: () => props.modelValue,
+ set: val => emit("update:modelValue", val),
+ });
+
+ const dialogTitle = computed(() => {
+ if (props.operationType === "add") return "鏂板鎵撳崱瑙勫垯";
+ if (props.operationType === "edit") return "缂栬緫鎵撳崱瑙勫垯";
+ return "鏌ョ湅鎵撳崱瑙勫垯";
+ });
+
+ // 琛ㄥ崟鏁版嵁
+ const formRef = ref();
+ const form = reactive({
+ id: "",
+ sysDeptId: "",
+ locationName: "",
+ longitude: "",
+ latitude: "",
+ radius: 100,
+ startAt: "09:00",
+ endAt: "18:00",
+ });
+
+ // 琛ㄥ崟楠岃瘉瑙勫垯
+ const rules = {
+ sysDeptId: [{ required: true, message: "璇烽�夋嫨閮ㄩ棬", trigger: "change" }],
+ locationName: [
+ { required: true, message: "璇疯緭鍏ュ湴鐐瑰悕绉�", trigger: "blur" },
+ ],
+ longitude: [{ required: true, message: "璇烽�夋嫨鎵撳崱浣嶇疆", trigger: "blur" }],
+ latitude: [{ required: true, message: "璇烽�夋嫨鎵撳崱浣嶇疆", trigger: "blur" }],
+ radius: [{ required: true, message: "璇疯緭鍏ユ墦鍗¤寖鍥�", trigger: "blur" }],
+ startAt: [{ required: true, message: "璇烽�夋嫨涓婄彮鏃堕棿", trigger: "change" }],
+ endAt: [
+ { required: true, message: "璇烽�夋嫨涓嬬彮鏃堕棿", trigger: "change" },
+ {
+ validator: (rule, value, callback) => {
+ if (form.startAt && value) {
+ const startParts = form.startAt.split(":");
+ const endParts = value.split(":");
+ const startTime =
+ parseInt(startParts[0]) * 60 + parseInt(startParts[1]);
+ const endTime = parseInt(endParts[0]) * 60 + parseInt(endParts[1]);
+ if (endTime <= startTime) {
+ callback(new Error("涓嬬彮鏃堕棿涓嶈兘鏃╀簬涓婄彮鏃堕棿"));
+ } else {
+ callback();
+ }
+ } else {
+ callback();
+ }
+ },
+ trigger: "change",
+ },
+ ],
+ };
+
+ // 閮ㄩ棬閫夐」
+ const deptOptions = ref([]);
+
+ // 鍦板浘鐩稿叧
+ const mapContainer = ref(null);
+ let map = null;
+ let marker = null;
+ let circle = null;
+
+ // 鑾峰彇閮ㄩ棬鍒楄〃
+ const fetchDeptOptions = () => {
+ deptTreeSelect().then(response => {
+ deptOptions.value = filterDisabledDept(
+ JSON.parse(JSON.stringify(response.data))
+ );
+ });
+ };
+
+ // 杩囨护绂佺敤鐨勯儴闂�
+ const filterDisabledDept = deptList => {
+ return deptList.filter(dept => {
+ if (dept.disabled) {
+ return false;
+ }
+ if (dept.children && dept.children.length) {
+ dept.children = filterDisabledDept(dept.children);
+ }
+ return true;
+ });
+ };
+
+ // 鍒濆鍖栧湴鍥�
+ const initMap = () => {
+ nextTick(() => {
+ if (window.AMap && mapContainer.value) {
+ // 鍒濆鍖栧湴鍥�
+ map = new window.AMap.Map(mapContainer.value, {
+ zoom: 16,
+ center: [116.397428, 39.90923], // 榛樿鍖椾含
+ });
+
+ // 娣诲姞鎺т欢
+ window.AMap.plugin(["AMap.ToolBar", "AMap.Scale"], function () {
+ map.addControl(new window.AMap.ToolBar());
+ map.addControl(new window.AMap.Scale());
+ });
+
+ // 娣诲姞鏍囪
+ marker = new window.AMap.Marker({
+ position: [116.397428, 39.90923],
+ draggable: true,
+ cursor: "move",
+ title: "鎷栨嫿瀹氫綅",
+ });
+ map.add(marker);
+
+ // 娣诲姞鍦嗗舰鑼冨洿
+ circle = new window.AMap.Circle({
+ center: [116.397428, 39.90923],
+ radius: form.radius,
+ strokeColor: "#3366FF",
+ strokeOpacity: 0.8,
+ strokeWeight: 2,
+ fillColor: "#3366FF",
+ fillOpacity: 0.2,
+ });
+ map.add(circle);
+
+ // 鐩戝惉鏍囪鎷栨嫿
+ marker.on("dragend", e => {
+ const position = e.lnglat;
+ const lng = position.getLng();
+ const lat = position.getLat();
+ form.longitude = lng;
+ form.latitude = lat;
+ updateCircle(position);
+ });
+
+ // 鐩戝惉鏍囪鎷栨嫿寮�濮�
+ marker.on("dragstart", () => {
+ map.setDefaultCursor("move");
+ });
+
+ // 鐩戝惉鏍囪鎷栨嫿缁撴潫
+ marker.on("dragend", () => {
+ map.setDefaultCursor("default");
+ });
+
+ // 鐩戝惉鍦板浘鐐瑰嚮
+ map.on("click", e => {
+ const position = e.lnglat;
+ const lng = position.getLng();
+ const lat = position.getLat();
+ form.longitude = lng;
+ form.latitude = lat;
+ updateMarker(position);
+ updateCircle(position);
+ });
+
+ // 灏濊瘯鑾峰彇褰撳墠浣嶇疆骞惰缃负鍦板浘涓績
+ if (navigator.geolocation && !form.longitude && !form.latitude) {
+ navigator.geolocation.getCurrentPosition(
+ position => {
+ console.log("鑾峰彇鍒板綋鍓嶄綅缃�:", position);
+ const { longitude, latitude } = position.coords;
+ const currentPosition = [longitude, latitude];
+ map.setCenter(currentPosition);
+ updateMarker(currentPosition);
+ updateCircle(currentPosition);
+ form.longitude = longitude;
+ form.latitude = latitude;
+ },
+ error => {
+ console.log("鑾峰彇浣嶇疆澶辫触锛屼娇鐢ㄩ粯璁や綅缃�");
+ }
+ );
+ } else if (form.longitude && form.latitude) {
+ // 濡傛灉鏈夋暟鎹紝璁剧疆鍒板湴鍥�
+ const position = [form.longitude, form.latitude];
+ map.setCenter(position);
+ updateMarker(position);
+ updateCircle(position);
+ }
+ }
+ });
+ };
+
+ // 鏇存柊鏍囪浣嶇疆
+ const updateMarker = position => {
+ if (marker) {
+ marker.setPosition(position);
+ }
+ };
+
+ // 鏇存柊鍦嗗舰鑼冨洿
+ const updateCircle = position => {
+ if (circle) {
+ circle.setCenter(position);
+ circle.setRadius(form.radius);
+ }
+ };
+
+ // 鑾峰彇褰撳墠浣嶇疆
+ const getCurrentLocation = () => {
+ if (navigator.geolocation) {
+ navigator.geolocation.getCurrentPosition(
+ position => {
+ const { longitude, latitude } = position.coords;
+ form.longitude = longitude;
+ form.latitude = latitude;
+ if (map) {
+ map.setCenter([longitude, latitude]);
+ updateMarker([longitude, latitude]);
+ updateCircle([longitude, latitude]);
+ }
+
+ // 閫嗗湴鐞嗙紪鐮佽幏鍙栧湴鍧�
+ if (window.AMap) {
+ // 鍔犺浇Geocoder鎻掍欢
+ window.AMap.plugin("AMap.Geocoder", function () {
+ const geocoder = new window.AMap.Geocoder();
+ geocoder.getAddress([longitude, latitude], (status, result) => {
+ if (status === "complete" && result.regeocode) {
+ form.locationName = result.regeocode.formattedAddress;
+ }
+ });
+ });
+ }
+ },
+ error => {
+ ElMessage.error("鑾峰彇浣嶇疆澶辫触锛岃鎵嬪姩閫夋嫨");
+ }
+ );
+ } else {
+ ElMessage.error("娴忚鍣ㄤ笉鏀寔鍦扮悊瀹氫綅");
+ }
+ };
+
+ // 鐩戝惉鍗婂緞鍙樺寲
+ watch(
+ () => form.radius,
+ newValue => {
+ if (circle) {
+ circle.setRadius(newValue);
+ }
+ }
+ );
+
+ // 鐩戝惉涓婄彮鏃堕棿鍙樺寲锛岃Е鍙戜笅鐝椂闂存牎楠�
+ watch(
+ () => form.startAt,
+ () => {
+ if (formRef.value && form.endAt) {
+ formRef.value.validateField("endAt");
+ }
+ }
+ );
+
+ // 鐩戝惉寮圭獥鏄剧ず
+ watch(
+ () => dialogVisible.value,
+ newValue => {
+ if (newValue) {
+ // 閲嶇疆琛ㄥ崟
+ Object.assign(form, {
+ id: "",
+ sysDeptId: "",
+ locationName: "",
+ longitude: "",
+ latitude: "",
+ radius: 100,
+ startAt: "09:00",
+ endAt: "18:00",
+ });
+
+ // 濡傛灉鏄紪杈戞垨鏌ョ湅锛屽~鍏呮暟鎹�
+ if (props.operationType !== "add" && props.row.id) {
+ // 澶勭悊鏃堕棿鏍煎紡锛岀‘淇濇槸HH:mm鏍煎紡
+ const rowData = { ...props.row };
+ if (rowData.startAt && rowData.startAt.includes(":")) {
+ rowData.startAt = rowData.startAt.split(":").slice(0, 2).join(":");
+ }
+ if (rowData.endAt && rowData.endAt.includes(":")) {
+ rowData.endAt = rowData.endAt.split(":").slice(0, 2).join(":");
+ }
+ Object.assign(form, rowData);
+ }
+
+ // 鍒濆鍖栧湴鍥�
+ setTimeout(() => {
+ initMap();
+ }, 100);
+ }
+ }
+ );
+
+ // 鎻愪氦琛ㄥ崟
+ const submitForm = () => {
+ formRef.value.validate(valid => {
+ if (valid) {
+ const submitData = {
+ ...form,
+ // 杞崲鏃堕棿鏍煎紡锛岀‘淇濆彧淇濈暀鏃跺垎閮ㄥ垎
+ startAt: form.startAt
+ ? `${form.startAt.split(":").slice(0, 2).join(":")}`
+ : null,
+ endAt: form.endAt
+ ? `${form.endAt.split(":").slice(0, 2).join(":")}`
+ : null,
+ };
+
+ if (props.operationType === "add") {
+ addAttendanceRule(submitData).then(() => {
+ ElMessage.success("鏂板鎴愬姛");
+ emit("close");
+ });
+ } else if (props.operationType === "edit") {
+ addAttendanceRule(submitData).then(() => {
+ ElMessage.success("鏇存柊鎴愬姛");
+ emit("close");
+ });
+ }
+ }
+ });
+ };
+
+ // 鍒濆鍖�
+ onMounted(() => {
+ fetchDeptOptions();
+ });
+</script>
+
+<style scoped lang="scss">
+ .map-container {
+ width: 100%;
+ }
+
+ .map {
+ width: 100%;
+ height: 400px;
+ border: 1px solid #e4e7ed;
+ }
+
+ .coordinates-info {
+ display: flex;
+ gap: 10px;
+ }
+
+ .coordinates-display {
+ padding: 10px;
+ background-color: #f5f7fa;
+ border-radius: 4px;
+ }
+
+ .mt10 {
+ margin-top: 10px;
+ }
+
+ .mt8 {
+ margin-top: 8px;
+ }
+</style>
\ No newline at end of file
diff --git a/src/views/personnelManagement/attendanceCheckin/checkinRules/index.vue b/src/views/personnelManagement/attendanceCheckin/checkinRules/index.vue
new file mode 100644
index 0000000..1fd19f3
--- /dev/null
+++ b/src/views/personnelManagement/attendanceCheckin/checkinRules/index.vue
@@ -0,0 +1,293 @@
+<template>
+ <div class="app-container">
+ <!-- 椤甸潰鏍囬鍜屾搷浣滄寜閽� -->
+ <div class="page-header">
+ <div class="title">鎵撳崱瑙勫垯閰嶇疆</div>
+ <div class="actions">
+ <el-button type="primary"
+ @click="openForm('add')">
+ <el-icon>
+ <Plus />
+ </el-icon>
+ 鏂板瑙勫垯
+ </el-button>
+ </div>
+ </div>
+ <!-- 鏌ヨ鏉′欢 -->
+ <!-- <el-form :model="searchForm"
+ :inline="true"
+ class="search-form mb16">
+ <el-form-item label="閮ㄩ棬锛�"
+ prop="countId">
+ <el-tree-select v-model="searchForm.countId"
+ :data="deptOptions"
+ :props="{ value: 'id', label: 'label', children: 'children' }"
+ value-key="id"
+ placeholder="璇烽�夋嫨閮ㄩ棬"
+ check-strictly
+ style="width: 200px" />
+ </el-form-item>
+ <el-form-item label="鍦扮偣锛�"
+ prop="locationName">
+ <el-input v-model="searchForm.locationName"
+ placeholder="璇疯緭鍏ュ湴鐐瑰悕绉�"
+ clearable
+ style="width: 200px" />
+ </el-form-item>
+ <el-form-item>
+ <el-button type="primary"
+ @click="fetchData">
+ <el-icon>
+ <Search />
+ </el-icon>
+ 鎼滅储
+ </el-button>
+ <el-button @click="resetSearch">
+ <el-icon>
+ <Refresh />
+ </el-icon>
+ 閲嶇疆
+ </el-button>
+ </el-form-item>
+ </el-form> -->
+ <!-- 瑙勫垯鍒楄〃 -->
+ <el-card shadow="never"
+ class="mb16">
+ <el-table :data="tableData"
+ border
+ v-loading="tableLoading"
+ style="width: 100%"
+ row-key="id">
+ <el-table-column type="index"
+ label="搴忓彿"
+ width="60"
+ align="center" />
+ <el-table-column label="閮ㄩ棬">
+ <template #default="scope">
+ {{ getDeptNameById(scope.row.sysDeptId) }}
+ </template>
+ </el-table-column>
+ <el-table-column prop="locationName"
+ label="鍦扮偣鍚嶇О" />
+ <el-table-column prop="longitude"
+ label="缁忓害" />
+ <el-table-column prop="latitude"
+ label="绾害" />
+ <el-table-column prop="radius"
+ label="鎵撳崱鑼冨洿(m)" />
+ <el-table-column prop="startAt"
+ label="涓婄彮鏃堕棿">
+ <template #default="scope">
+ {{ scope.row.startAt }}
+ </template>
+ </el-table-column>
+ <el-table-column prop="endAt"
+ label="涓嬬彮鏃堕棿">
+ <template #default="scope">
+ {{ scope.row.endAt }}
+ </template>
+ </el-table-column>
+ <el-table-column label="鎿嶄綔"
+ width="180"
+ fixed="right"
+ align="center">
+ <template #default="scope">
+ <el-button type="primary"
+ size="small"
+ link
+ @click="openForm('edit', scope.row)">缂栬緫</el-button>
+ <el-button type="danger"
+ size="small"
+ link
+ @click="handleDelete(scope.row.id)">鍒犻櫎</el-button>
+ </template>
+ </el-table-column>
+ </el-table>
+ <pagination :total="page.total"
+ layout="total, sizes, prev, pager, next, jumper"
+ :page="page.current"
+ :limit="page.size"
+ @pagination="paginationChange"
+ class="mt10" />
+ </el-card>
+ <!-- 鏂板/缂栬緫瑙勫垯寮圭獥 -->
+ <rule-form ref="ruleFormRef"
+ v-model="dialogVisible"
+ :operation-type="operationType"
+ :row="currentRow"
+ @close="dialogVisible = false; fetchData()" />
+ </div>
+</template>
+
+<script setup>
+ import { ref, reactive, onMounted } from "vue";
+ import { ElMessage, ElMessageBox } from "element-plus";
+ import { Plus, Edit, Delete, Search, Refresh } from "@element-plus/icons-vue";
+ import Pagination from "@/components/Pagination/index.vue";
+ import RuleForm from "./components/form.vue";
+ import { deptTreeSelect } from "@/api/system/user.js";
+ import {
+ getAttendanceRules,
+ deleteAttendanceRule,
+ } from "@/api/personnelManagement/attendanceRules.js";
+
+ const { proxy } = getCurrentInstance();
+
+ // 琛ㄦ牸鏁版嵁
+ const tableData = ref([]);
+ const tableLoading = ref(false);
+
+ // 鍒嗛〉鍙傛暟
+ const page = reactive({
+ current: 1,
+ size: 10,
+ total: 0,
+ });
+
+ // 鏌ヨ琛ㄥ崟
+ const searchForm = reactive({
+ countId: "",
+ locationName: "",
+ });
+
+ // 閮ㄩ棬閫夐」
+ const deptOptions = ref([]);
+
+ // 寮圭獥鎺у埗
+ const dialogVisible = ref(false);
+ const operationType = ref("add");
+ const currentRow = ref({});
+ const ruleFormRef = ref();
+
+ // 鏍煎紡鍖栨椂闂�
+ const formatTime = timestamp => {
+ if (!timestamp) return "";
+ const date = new Date(timestamp);
+ return `${String(date.getHours()).padStart(2, "0")}:${String(
+ date.getMinutes()
+ ).padStart(2, "0")}`;
+ };
+
+ // 鑾峰彇閮ㄩ棬鍒楄〃
+ const fetchDeptOptions = () => {
+ deptTreeSelect().then(response => {
+ deptOptions.value = filterDisabledDept(
+ JSON.parse(JSON.stringify(response.data))
+ );
+ });
+ };
+
+ // 杩囨护绂佺敤鐨勯儴闂�
+ const filterDisabledDept = deptList => {
+ return deptList.filter(dept => {
+ if (dept.disabled) {
+ return false;
+ }
+ if (dept.children && dept.children.length) {
+ dept.children = filterDisabledDept(dept.children);
+ }
+ return true;
+ });
+ };
+
+ // 鏍规嵁閮ㄩ棬ID鏌ユ壘閮ㄩ棬鍚嶇О
+ const getDeptNameById = (deptId, deptList = deptOptions.value) => {
+ for (const dept of deptList) {
+ if (dept.id === deptId) {
+ return dept.label;
+ }
+ if (dept.children && dept.children.length) {
+ const name = getDeptNameById(deptId, dept.children);
+ if (name) {
+ return name;
+ }
+ }
+ }
+ return "";
+ };
+
+ // 鏌ヨ瑙勫垯鍒楄〃
+ const fetchData = () => {
+ tableLoading.value = true;
+ getAttendanceRules({ ...page, ...searchForm })
+ .then(res => {
+ tableData.value = res.data.records;
+ page.total = res.data.total;
+ })
+ .finally(() => {
+ tableLoading.value = false;
+ });
+ };
+
+ // 鍒嗛〉鍙樻洿
+ const paginationChange = pagination => {
+ page.current = pagination.page;
+ page.size = pagination.limit;
+ fetchData();
+ };
+
+ // 閲嶇疆鎼滅储
+ const resetSearch = () => {
+ searchForm.countId = "";
+ searchForm.locationName = "";
+ fetchData();
+ };
+
+ // 鎵撳紑琛ㄥ崟
+ const openForm = (type, row = {}) => {
+ operationType.value = type;
+ currentRow.value = row;
+ dialogVisible.value = true;
+ };
+
+ // 鍒犻櫎瑙勫垯
+ const handleDelete = id => {
+ ElMessageBox.confirm("纭畾瑕佸垹闄よ繖鏉¤鍒欏悧锛�", "鍒犻櫎纭", {
+ confirmButtonText: "纭畾",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ })
+ .then(() => {
+ deleteAttendanceRule([id]).then(() => {
+ ElMessage.success("鍒犻櫎鎴愬姛");
+ fetchData();
+ });
+ })
+ .catch(() => {
+ // 鍙栨秷鍒犻櫎
+ });
+ };
+
+ // 鍒濆鍖�
+ onMounted(() => {
+ fetchDeptOptions();
+ fetchData();
+ });
+</script>
+
+<style scoped lang="scss">
+ .page-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 20px;
+
+ .title {
+ font-size: 18px;
+ font-weight: 600;
+ }
+
+ .actions {
+ display: flex;
+ gap: 10px;
+ }
+ }
+
+ .mb16 {
+ margin-bottom: 16px;
+ }
+
+ .mt10 {
+ margin-top: 10px;
+ }
+</style>
\ No newline at end of file
diff --git a/src/views/personnelManagement/attendanceCheckin/index.vue b/src/views/personnelManagement/attendanceCheckin/index.vue
new file mode 100644
index 0000000..f2d8776
--- /dev/null
+++ b/src/views/personnelManagement/attendanceCheckin/index.vue
@@ -0,0 +1,507 @@
+<template>
+ <div class="app-container">
+ <!-- 鍛樺伐鎵撳崱鍖� -->
+ <!-- <el-card shadow="never"
+ class="mb16">
+ <div class="attendance-header">
+ <div>
+ <div class="title">鎵撳崱绛惧埌
+ </div>
+ <div class="sub-title">鏀寔涓�閿墦鍗★紝鑷姩璁板綍涓婁笅鐝椂闂�</div>
+ </div>
+ <div class="attendance-actions">
+ <div class="time-block">
+ <div class="label">褰撳墠鏃堕棿</div>
+ <div class="value">{{ nowTime }}</div>
+ </div>
+ <el-button type="primary"
+ size="large"
+ @click="handleCheckInOut"
+ :disabled="todayRecord.workEndAt">
+ {{ checkInOutText }}
+ </el-button>
+ </div>
+ </div>
+ <el-descriptions border
+ :column="4"
+ class="mt10">
+ <el-descriptions-item label="鍛樺伐濮撳悕">
+ {{ todayRecord.staffName }}
+ </el-descriptions-item>
+ <el-descriptions-item label="宸ュ彿">
+ {{ todayRecord.staffNo }}
+ </el-descriptions-item>
+ <el-descriptions-item label="鎵�灞為儴闂�">
+ {{ todayRecord.deptName }}
+ </el-descriptions-item>
+ <el-descriptions-item label="浠婃棩鐘舵��">
+ <el-tag :type="todayStatusTag"
+ size="small">
+ {{ todayStatusText }}
+ </el-tag>
+ </el-descriptions-item>
+ <el-descriptions-item label="涓婄彮鏃堕棿">
+ {{ todayRecord?.workStartAt || '-' }}
+ </el-descriptions-item>
+ <el-descriptions-item label="涓嬬彮鏃堕棿">
+ {{ todayRecord?.workEndAt || '-' }}
+ </el-descriptions-item>
+ <el-descriptions-item label="宸ユ椂(灏忔椂)">
+ {{ todayRecord?.workHours ?? '-' }}
+ </el-descriptions-item>
+ <el-descriptions-item label="寮傚父鏍囪">
+ <span v-if="!todayRecord.id || todayRecord?.status === 0">-</span>
+ <el-tag v-else
+ type="danger"
+ size="small">
+ {{ todayRecord?.status ? getStatusText(todayRecord.status) : '-' }}
+ </el-tag>
+ </el-descriptions-item>
+ </el-descriptions>
+ </el-card> -->
+ <div class="attendance-operation">
+ <!-- 鏌ヨ鏉′欢锛堢鐞嗗憳鑰冨嫟鏃ユ姤锛� -->
+ <el-form :model="searchForm"
+ :inline="true"
+ class="search-form">
+ <el-form-item label="閮ㄩ棬锛�"
+ prop="deptId">
+ <el-tree-select v-model="searchForm.deptId"
+ :data="deptOptions"
+ :props="{ value: 'id', label: 'label', children: 'children' }"
+ value-key="id"
+ placeholder="璇烽�夋嫨閮ㄩ棬"
+ check-strictly
+ style="width: 200px" />
+ </el-form-item>
+ <el-form-item label="鏃ユ湡锛�"
+ prop="date">
+ <el-date-picker v-model="searchForm.date"
+ type="date"
+ value-format="YYYY-MM-DD"
+ format="YYYY-MM-DD"
+ placeholder="璇烽�夋嫨鏃ユ湡"
+ clearable />
+ </el-form-item>
+ <el-form-item>
+ <el-button type="primary"
+ @click="fetchData">
+ <el-icon>
+ <Search />
+ </el-icon>
+ 鎼滅储
+ </el-button>
+ <el-button @click="resetSearch">
+ <el-icon>
+ <Refresh />
+ </el-icon>
+ 閲嶇疆
+ </el-button>
+ </el-form-item>
+ </el-form>
+ <el-button icon="Download"
+ @click="handleExport">
+ 瀵煎嚭鑰冨嫟鏃ユ姤
+ </el-button>
+ </div>
+ <!-- 鑰冨嫟鏃ユ姤琛ㄦ牸 -->
+ <div class="table_list">
+ <el-table :data="tableData"
+ border
+ v-loading="tableLoading"
+ style="width: 100%"
+ height="calc(100vh - 24em)"
+ :header-cell-style="{ background: '#F0F1F5', color: '#333333' }"
+ :row-class-name="rowClassName">
+ <el-table-column type="index"
+ label="搴忓彿"
+ width="60"
+ align="center" />
+ <el-table-column prop="date"
+ label="鏃ユ湡"
+ width="120" />
+ <el-table-column prop="deptName"
+ label="閮ㄩ棬"
+ width="140" />
+ <el-table-column prop="staffName"
+ label="濮撳悕"
+ width="120" />
+ <el-table-column prop="staffNo"
+ label="宸ュ彿"
+ width="120" />
+ <el-table-column prop="workStartAt"
+ label="涓婄彮鏃堕棿"
+ width="140" />
+ <el-table-column prop="workEndAt"
+ label="涓嬬彮鏃堕棿"
+ width="140" />
+ <el-table-column prop="workHours"
+ label="宸ユ椂(灏忔椂)"
+ align="center" />
+ <el-table-column prop="status"
+ label="鑰冨嫟鐘舵��"
+ align="center">
+ <template #default="scope">
+ <el-tag v-if="scope.row.status === 0"
+ type="success"
+ size="small">
+ 姝e父
+ </el-tag>
+ <el-tag v-else
+ type="danger"
+ size="small">
+ <!-- {{ scope.row.status === 1 ? '杩熷埌' : scope.row.status === 2 ? '鏃╅��' : '杩熷埌銆佹棭閫�' }} -->
+ {{ getStatusText(scope.row.status) }}
+ </el-tag>
+ </template>
+ </el-table-column>
+ <el-table-column prop="remark"
+ label="澶囨敞"
+ show-overflow-tooltip />
+ </el-table>
+ <pagination :total="page.total"
+ layout="total, sizes, prev, pager, next, jumper"
+ :page="page.current"
+ :limit="page.size"
+ @pagination="paginationChange" />
+ </div>
+ </div>
+</template>
+
+<script setup>
+ import { ref, reactive, computed, onMounted, onBeforeUnmount } from "vue";
+ import { ElMessage, ElMessageBox } from "element-plus";
+ import {
+ createPersonalAttendanceRecord,
+ findPersonalAttendanceRecords,
+ findTodayPersonalAttendanceRecord,
+ } from "@/api/personnelManagement/personalAttendanceRecords.js";
+ import Pagination from "@/components/Pagination/index.vue";
+ import { deptTreeSelect } from "@/api/system/user.js";
+ import { Refresh, Search } from "@element-plus/icons-vue";
+
+ const { proxy } = getCurrentInstance();
+ const tableLoading = ref(false);
+ // 鍒嗛〉鍙傛暟
+ const page = reactive({
+ current: 1,
+ size: 10,
+ total: 0,
+ });
+ // 浠婃棩鏁版嵁
+ const todayRecord = ref({});
+
+ // 閮ㄩ棬閫夐」
+ const deptOptions = ref([]);
+
+ // 鏌ヨ琛ㄥ崟
+ const searchForm = reactive({
+ deptId: "",
+ date: "",
+ });
+
+ // 琛ㄦ牸鏁版嵁
+ const tableData = ref([]);
+
+ // 褰撳墠鏃堕棿灞曠ず
+ const nowTime = ref("");
+ let timer = null;
+
+ const updateNowTime = () => {
+ const now = new Date();
+ const Y = now.getFullYear();
+ const M = String(now.getMonth() + 1).padStart(2, "0");
+ const D = String(now.getDate()).padStart(2, "0");
+ const h = String(now.getHours()).padStart(2, "0");
+ const m = String(now.getMinutes()).padStart(2, "0");
+ const s = String(now.getSeconds()).padStart(2, "0");
+ nowTime.value = `${Y}-${M}-${D} ${h}:${m}:${s}`;
+ };
+
+ // 鎵撳崱鎸夐挳鏂囨湰
+ const checkInOutText = computed(() => {
+ if (!todayRecord.value || !todayRecord.value.workStartAt) {
+ return "涓婄彮鎵撳崱";
+ }
+ if (!todayRecord.value.workEndAt) {
+ return "涓嬬彮鎵撳崱";
+ }
+ return "浠婃棩宸叉墦鍗″畬鎴�";
+ });
+
+ // 浠婃棩鐘舵�佸睍绀�
+ const todayStatusTag = computed(() => {
+ if (!todayRecord.value.id) return "info";
+ if (todayRecord.value.status === 0) return "success";
+ return "danger";
+ });
+ const getStatusText = status => {
+ switch (status) {
+ case 0:
+ return "姝e父";
+ case 1:
+ return "杩熷埌";
+ case 2:
+ return "鏃╅��";
+ case 3:
+ return "杩熷埌銆佹棭閫�";
+ case 4:
+ return "缂哄嫟";
+ }
+ };
+
+ const todayStatusText = computed(() => {
+ if (!todayRecord.value.id) return "鏈墦鍗�";
+ switch (todayRecord.value.status) {
+ case 0:
+ return "姝e父";
+ case 1:
+ return "杩熷埌";
+ case 2:
+ return "鏃╅��";
+ case 3:
+ return "杩熷埌銆佹棭閫�";
+ case 4:
+ return "缂哄嫟";
+ }
+ });
+
+ // 琛屾牱寮忥細寮傚父楂樹寒
+ const rowClassName = ({ row }) => {
+ if (row.status === 1 || row.status === 2) {
+ return "row-abnormal";
+ }
+ return "";
+ };
+
+ // 鏌ヨ閮ㄩ棬鍒楄〃
+ const fetchDeptOptions = () => {
+ deptTreeSelect().then(response => {
+ deptOptions.value = filterDisabledDept(
+ JSON.parse(JSON.stringify(response.data))
+ );
+ });
+ };
+
+ /** 杩囨护绂佺敤鐨勯儴闂� */
+ function filterDisabledDept(deptList) {
+ return deptList.filter(dept => {
+ if (dept.disabled) {
+ return false;
+ }
+ if (dept.children && dept.children.length) {
+ dept.children = filterDisabledDept(dept.children);
+ }
+ return true;
+ });
+ }
+
+ // 鏌ヨ
+ const fetchData = () => {
+ tableLoading.value = true;
+ findPersonalAttendanceRecords({ ...page, ...searchForm })
+ .then(res => {
+ tableData.value = res.data.records;
+ page.total = res.data.total;
+ })
+ .finally(() => {
+ tableLoading.value = false;
+ });
+ };
+
+ // 鏌ヨ浠婃棩鎵撳崱淇℃伅
+ const fetchTodayData = () => {
+ // findTodayPersonalAttendanceRecord({}).then(res => {
+ // todayRecord.value = res.data;
+ // });
+ };
+
+ const paginationChange = pagination => {
+ page.current = pagination.page;
+ page.size = pagination.limit;
+ fetchData();
+ };
+
+ const resetSearch = () => {
+ searchForm.deptId = "";
+ searchForm.date = "";
+ fetchData();
+ };
+
+ const handleExport = () => {
+ ElMessageBox.confirm("鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ })
+ .then(() => {
+ proxy.download("/personalAttendanceRecords/export", {}, "鑰冨嫟璁板綍.xlsx");
+ })
+ .catch(() => {
+ proxy.$modal.msg("宸插彇娑�");
+ });
+ };
+
+ // 鑾峰彇褰撳墠浣嶇疆
+ const getCurrentLocation = () => {
+ return new Promise((resolve, reject) => {
+ if (!navigator.geolocation) {
+ reject(new Error("娴忚鍣ㄤ笉鏀寔鍦扮悊瀹氫綅"));
+ return;
+ }
+
+ // 妫�鏌ユ槸鍚︿娇鐢℉TTPS
+ const isSecureContext =
+ window.isSecureContext || window.location.protocol === "https:";
+ console.log(
+ "褰撳墠鍗忚:",
+ window.location.protocol,
+ "鏄惁瀹夊叏涓婁笅鏂�:",
+ isSecureContext
+ );
+
+ if (!isSecureContext) {
+ console.warn("褰撳墠涓嶆槸HTTPS鍗忚锛屽湴鐞嗕綅缃瓵PI鍙兘鍙楅檺");
+ }
+
+ navigator.geolocation.getCurrentPosition(
+ position => {
+ const { longitude, latitude } = position.coords;
+ console.log("鑾峰彇浣嶇疆鎴愬姛:", longitude, latitude);
+ resolve({ longitude, latitude });
+ },
+ error => {
+ console.log("鑾峰彇浣嶇疆澶辫触:", error);
+ let errorMessage = "鑾峰彇浣嶇疆澶辫触";
+
+ // 鏍规嵁閿欒绫诲瀷鎻愪緵鏇村叿浣撶殑鎻愮ず
+ switch (error.code) {
+ case error.PERMISSION_DENIED:
+ errorMessage =
+ "鐢ㄦ埛鎷掔粷浜嗕綅缃潈闄愯姹傦紝璇峰湪娴忚鍣ㄨ缃腑鍏佽浣嶇疆璁块棶";
+ break;
+ case error.POSITION_UNAVAILABLE:
+ errorMessage = "浣嶇疆淇℃伅涓嶅彲鐢紝璇锋鏌ヨ澶囧畾浣嶅姛鑳�";
+ break;
+ case error.TIMEOUT:
+ errorMessage = "鑾峰彇浣嶇疆瓒呮椂锛岃閲嶈瘯";
+ break;
+ case error.UNKNOWN_ERROR:
+ errorMessage = "鑾峰彇浣嶇疆鏃跺彂鐢熸湭鐭ラ敊璇�";
+ break;
+ default:
+ errorMessage = `鑾峰彇浣嶇疆澶辫触: ${error.message}`;
+ }
+
+ // 妫�鏌ユ槸鍚︽槸HTTPS闂
+ if (error.code === error.PERMISSION_DENIED && !isSecureContext) {
+ errorMessage += "锛堟敞鎰忥細鐢熶骇鐜闇�瑕佷娇鐢℉TTPS鍗忚鎵嶈兘鑾峰彇浣嶇疆锛�";
+ }
+
+ reject(new Error(errorMessage));
+ },
+ {
+ enableHighAccuracy: true,
+ timeout: 10000,
+ maximumAge: 0,
+ }
+ );
+ });
+ };
+
+ // 鎵撳崱
+ const handleCheckInOut = () => {
+ getCurrentLocation()
+ .then(location => {
+ console.log("浣嶇疆鎴愬姛");
+ createPersonalAttendanceRecord(location).then(res => {
+ fetchData();
+ fetchTodayData();
+ ElMessage.success("鎵撳崱鎴愬姛锛�");
+ });
+ })
+ .catch(error => {
+ // 鑾峰彇浣嶇疆澶辫触鏃讹紝浠嶅厑璁告墦鍗�
+ ElMessage.warning("鑾峰彇浣嶇疆澶辫触锛屽皢浣跨敤榛樿浣嶇疆鎵撳崱");
+ createPersonalAttendanceRecord({}).then(res => {
+ fetchData();
+ fetchTodayData();
+ ElMessage.success("鎵撳崱鎴愬姛锛�");
+ });
+ });
+ };
+
+ onMounted(() => {
+ updateNowTime();
+ timer = setInterval(updateNowTime, 1000);
+ // 榛樿灞曠ず褰撳ぉ鏁版嵁
+ const today = new Date();
+ const Y = today.getFullYear();
+ const M = String(today.getMonth() + 1).padStart(2, "0");
+ const D = String(today.getDate()).padStart(2, "0");
+ searchForm.date = `${Y}-${M}-${D}`;
+ fetchData();
+ fetchTodayData();
+ fetchDeptOptions();
+ });
+
+ onBeforeUnmount(() => {
+ if (timer) {
+ clearInterval(timer);
+ }
+ });
+</script>
+
+<style scoped lang="scss">
+ .mb16 {
+ margin-bottom: 16px;
+ }
+
+ .attendance-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ }
+
+ .attendance-header .title {
+ font-size: 18px;
+ font-weight: 600;
+ margin-bottom: 4px;
+ }
+
+ .attendance-header .sub-title {
+ font-size: 13px;
+ color: #909399;
+ }
+
+ .attendance-actions {
+ display: flex;
+ align-items: center;
+ gap: 16px;
+ }
+
+ .time-block {
+ text-align: right;
+ }
+
+ .time-block .label {
+ font-size: 12px;
+ color: #909399;
+ }
+
+ .time-block .value {
+ font-size: 18px;
+ font-weight: 600;
+ color: #333;
+ }
+
+ ::v-deep(.row-abnormal) {
+ background-color: #fff5f5;
+ }
+
+ .attendance-operation {
+ display: flex;
+ justify-content: space-between;
+ }
+</style>
+
diff --git a/src/views/personnelManagement/contractManagement/components/formDia.vue b/src/views/personnelManagement/contractManagement/components/formDia.vue
index a124c1b..54b2ef9 100644
--- a/src/views/personnelManagement/contractManagement/components/formDia.vue
+++ b/src/views/personnelManagement/contractManagement/components/formDia.vue
@@ -11,7 +11,6 @@
:column="tableColumn"
:tableData="tableData"
:tableLoading="tableLoading"
- :showPagination="false"
height="600"
></PIMTable>
<template #footer>
@@ -20,22 +19,24 @@
</div>
</template>
</el-dialog>
+ <Files ref="filesDia"></Files>
</div>
</template>
<script setup>
import {ref} from "vue";
-import {staffOnJobInfo} from "@/api/personnelManagement/employeeRecord.js";
+import {findStaffContractListPage} from "@/api/personnelManagement/staffContract.js";
+const Files = defineAsyncComponent(() => import( "@/views/personnelManagement/contractManagement/filesDia.vue"));
const { proxy } = getCurrentInstance()
const emit = defineEmits(['close'])
-
+const filesDia = ref()
const dialogFormVisible = ref(false);
const operationType = ref('')
const tableColumn = ref([
- // {
- // label: "鍚堝悓骞撮檺",
- // prop: "contractTerm",
- // },
+ {
+ label: "鍚堝悓骞撮檺",
+ prop: "contractTerm",
+ },
{
label: "鍚堝悓寮�濮嬫棩鏈�",
prop: "contractStartTime",
@@ -43,6 +44,22 @@
{
label: "鍚堝悓缁撴潫鏃ユ湡",
prop: "contractEndTime",
+ },
+ {
+ dataType: "action",
+ label: "鎿嶄綔",
+ align: "center",
+ fixed: 'right',
+ width: 120,
+ operation: [
+ {
+ name: "涓婁紶闄勪欢",
+ type: "text",
+ clickFun: (row) => {
+ filesDia.value.openDialog( row,'鍚堝悓')
+ },
+ }
+ ],
},
]);
const tableData = ref([]);
@@ -53,12 +70,17 @@
operationType.value = type;
dialogFormVisible.value = true;
if (operationType.value === 'edit') {
- staffOnJobInfo({staffNo: row.staffNo}).then(res => {
- tableData.value = res.data
+ findStaffContractListPage({staffOnJobId: row.id}).then(res => {
+ tableData.value = res.data.records
})
}
}
+const openUploadFile = (row) => {
+ filesDia.value.open = true
+ filesDia.value.row = row
+}
+
// 鍏抽棴寮规
const closeDia = () => {
dialogFormVisible.value = false;
diff --git a/src/views/personnelManagement/contractManagement/filesDia.vue b/src/views/personnelManagement/contractManagement/filesDia.vue
index f752496..4bcd812 100644
--- a/src/views/personnelManagement/contractManagement/filesDia.vue
+++ b/src/views/personnelManagement/contractManagement/filesDia.vue
@@ -28,18 +28,13 @@
:tableData="tableData"
:tableLoading="tableLoading"
:isSelection="true"
+ :page="page"
@selection-change="handleSelectionChange"
height="500"
+ @pagination="paginationSearch"
+ :total="page.total"
>
</PIMTable>
- <pagination
- style="margin: 10px 0"
- v-show="total > 0"
- @pagination="paginationSearch"
- :total="total"
- :page="page.current"
- :limit="page.size"
- />
<template #footer>
<div class="dialog-footer">
<el-button @click="closeDia">鍙栨秷</el-button>
@@ -124,7 +119,7 @@
const getList = () => {
fileListPage({accountId: currentId.value,accountType:accountType.value, ...page}).then(res => {
tableData.value = res.data.records;
- total.value = res.data.total;
+ page.total = res.data.total;
})
}
// 琛ㄦ牸閫夋嫨鏁版嵁
diff --git a/src/views/personnelManagement/contractManagement/index.vue b/src/views/personnelManagement/contractManagement/index.vue
index 30aefb9..1d2aab7 100644
--- a/src/views/personnelManagement/contractManagement/index.vue
+++ b/src/views/personnelManagement/contractManagement/index.vue
@@ -70,11 +70,11 @@
</template>
<script setup>
-import { Search, UploadFilled } from "@element-plus/icons-vue";
-import { onMounted, ref, reactive, toRefs, getCurrentInstance, nextTick } from "vue";
+import { Search } from "@element-plus/icons-vue";
+import { onMounted, ref } from "vue";
import FormDia from "@/views/personnelManagement/contractManagement/components/formDia.vue";
import { ElMessageBox } from "element-plus";
-import { staffOnJobListPage } from "@/api/personnelManagement/employeeRecord.js";
+import { staffOnJobListPage } from "@/api/personnelManagement/staffOnJob.js";
import dayjs from "dayjs";
import { getToken } from "@/utils/auth.js";
import FilesDia from "./filesDia.vue";
@@ -183,7 +183,7 @@
label: "鎿嶄綔",
align: "center",
fixed: 'right',
- width: 130,
+ width: 120,
operation: [
{
name: "璇︽儏",
@@ -191,14 +191,7 @@
clickFun: (row) => {
openForm("edit", row);
},
- },
- {
- name: "闄勪欢",
- type: "text",
- clickFun: (row) => {
- openFilesFormDia(row);
- },
- },
+ }
],
},
]);
@@ -245,6 +238,7 @@
tableLoading.value = true;
const params = { ...searchForm.value, ...page };
params.entryDate = undefined
+ params.staffState = 1
staffOnJobListPage(params).then(res => {
tableLoading.value = false;
tableData.value = res.data.records
@@ -272,7 +266,7 @@
type: "warning",
})
.then(() => {
- proxy.download("/staff/staffOnJob/export", {}, "鍚堝悓绠$悊.xlsx");
+ proxy.download("/staff/staffOnJob/export", {staffState: 1}, "鍚堝悓绠$悊.xlsx");
})
.catch(() => {
proxy.$modal.msg("宸插彇娑�");
diff --git a/src/views/personnelManagement/dimission/components/formDia.vue b/src/views/personnelManagement/dimission/components/formDia.vue
index 01bd35f..2b8a7fd 100644
--- a/src/views/personnelManagement/dimission/components/formDia.vue
+++ b/src/views/personnelManagement/dimission/components/formDia.vue
@@ -9,145 +9,143 @@
<!-- 鍛樺伐淇℃伅灞曠ず鍖哄煙 -->
<div class="info-section">
<div class="info-title">鍛樺伐淇℃伅</div>
- <el-row :gutter="30">
- <el-col :span="12">
- <div class="info-item">
- <span class="info-label">濮撳悕锛�</span>
- <el-select v-model="form.staffName" placeholder="璇烽�夋嫨浜哄憳" style="width: 100%" @change="handleSelect" filterable>
- <el-option
- v-for="item in personList"
- :key="item.id"
- :label="item.staffName"
- :value="item.staffName"
+ <el-form :model="form" label-width="200px" label-position="left" :rules="rules" ref="formRef" style="margin-top: 20px">
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="濮撳悕锛�" prop="staffOnJobId">
+ <el-select v-model="form.staffOnJobId"
+ placeholder="璇烽�夋嫨浜哄憳"
+ style="width: 100%"
+ :disabled="operationType === 'edit'"
+ @change="handleSelect">
+ <el-option
+ v-for="item in personList"
+ :key="item.id"
+ :label="item.staffName"
+ :value="item.id"
+ />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鍛樺伐缂栧彿锛�">
+ {{ currentStaffRecord.staffNo || '-' }}
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="鎬у埆锛�">
+ {{ currentStaffRecord.sex || '-' }}
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鎴风睄浣忓潃锛�">
+ {{ currentStaffRecord.nativePlace || '-' }}
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="宀椾綅锛�">
+ {{ currentStaffRecord.postName || '-' }}
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鐜颁綇鍧�锛�">
+ {{ currentStaffRecord.adress || '-' }}
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="绗竴瀛﹀巻锛�">
+ {{ currentStaffRecord.firstStudy || '-' }}
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="涓撲笟锛�">
+ {{ currentStaffRecord.profession || '-' }}
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="骞撮緞锛�">
+ {{ currentStaffRecord.age || '-' }}
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="鑱旂郴鐢佃瘽锛�">
+ {{ currentStaffRecord.phone || '-' }}
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="绱ф�ヨ仈绯讳汉锛�">
+ {{ currentStaffRecord.emergencyContact || '-' }}
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="绱ф�ヨ仈绯讳汉鑱旂郴鐢佃瘽锛�">
+ {{ currentStaffRecord.emergencyContactPhone || '-' }}
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="绂昏亴鍘熷洜锛�" prop="reason">
+ <el-select v-model="form.reason" placeholder="璇烽�夋嫨绂昏亴鍘熷洜" style="width: 100%" @change="handleSelectDimissionReason">
+ <el-option
+ v-for="(item, index) in dimissionReasonOptions"
+ :key="index"
+ :label="item.label"
+ :value="item.value"
+ />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="澶囨敞锛�" prop="remark" v-if="form.reason === 'other'">
+ <el-input
+ v-model="form.remark"
+ type="textarea"
+ :rows="3"
+ placeholder="澶囨敞"
+ maxlength="500"
+ show-word-limit
/>
- </el-select>
- </div>
- </el-col>
- <el-col :span="12">
- <div class="info-item">
- <span class="info-label">鍛樺伐缂栧彿锛�</span>
- <span class="info-value">{{ form.staffNo || '-' }}</span>
- </div>
- </el-col>
- </el-row>
- <el-row :gutter="30">
- <el-col :span="12">
- <div class="info-item">
- <span class="info-label">鎬у埆锛�</span>
- <span class="info-value">{{ form.sex || '-' }}</span>
- </div>
- </el-col>
- <el-col :span="12">
- <div class="info-item">
- <span class="info-label">鎴风睄浣忓潃锛�</span>
- <span class="info-value">{{ form.nativePlace || '-' }}</span>
- </div>
- </el-col>
- </el-row>
- <el-row :gutter="30">
- <el-col :span="12">
- <div class="info-item">
- <span class="info-label">宀椾綅锛�</span>
- <span class="info-value">{{ form.postJob || '-' }}</span>
- </div>
- </el-col>
- <el-col :span="12">
- <div class="info-item">
- <span class="info-label">鐜颁綇鍧�锛�</span>
- <span class="info-value">{{ form.adress || '-' }}</span>
- </div>
- </el-col>
- </el-row>
- <el-row :gutter="30">
- <el-col :span="12">
- <div class="info-item">
- <span class="info-label">绗竴瀛﹀巻锛�</span>
- <span class="info-value">{{ form.firstStudy || '-' }}</span>
- </div>
- </el-col>
- <el-col :span="12">
- <div class="info-item">
- <span class="info-label">涓撲笟锛�</span>
- <span class="info-value">{{ form.profession || '-' }}</span>
- </div>
- </el-col>
- </el-row>
- <el-row :gutter="30">
- <el-col :span="12">
- <div class="info-item">
- <span class="info-label">骞撮緞锛�</span>
- <span class="info-value">{{ form.age || '-' }}</span>
- </div>
- </el-col>
- </el-row>
- <el-row :gutter="30">
- <el-col :span="12">
- <div class="info-item">
- <span class="info-label">鑱旂郴鐢佃瘽锛�</span>
- <span class="info-value">{{ form.phone || '-' }}</span>
- </div>
- </el-col>
- <el-col :span="12">
- <div class="info-item">
- <span class="info-label">绱ф�ヨ仈绯讳汉锛�</span>
- <span class="info-value">{{ form.emergencyContact || '-' }}</span>
- </div>
- </el-col>
- </el-row>
- <el-row :gutter="30">
- <el-col :span="12">
- <div class="info-item">
- <span class="info-label">绱ф�ヨ仈绯讳汉鑱旂郴鐢佃瘽锛�</span>
- <span class="info-value">{{ form.emergencyContactPhone || '-' }}</span>
- </div>
- </el-col>
- </el-row>
- <el-row :gutter="30">
- <el-col :span="12">
- <div class="info-item">
- <span class="info-label">鍚堝悓寮�濮嬫棩鏈燂細</span>
- <span class="info-value">{{ form.contractStartTime || '-' }}</span>
- </div>
- </el-col>
- <el-col :span="12">
- <div class="info-item">
- <span class="info-label">鍚堝悓缁撴潫鏃ユ湡锛�</span>
- <span class="info-value">{{ form.contractExpireTime || '-' }}</span>
- </div>
- </el-col>
- </el-row>
+ </el-form-item>
+ </el-col>
+ </el-row>
+ </el-form>
+
+<!-- <el-row :gutter="30">-->
+<!-- <el-col :span="12">-->
+<!-- <div class="info-item">-->
+<!-- <span class="info-label">绂昏亴鍘熷洜锛�</span>-->
+<!-- <el-select v-model="form.reason" placeholder="璇烽�夋嫨浜哄憳" style="width: 100%" @change="handleSelect">-->
+<!-- <el-option-->
+<!-- v-for="(item, index) in dimissionReasonOptions"-->
+<!-- :key="index"-->
+<!-- :label="item.label"-->
+<!-- :value="item.value"-->
+<!-- />-->
+<!-- </el-select>-->
+<!-- </div>-->
+<!-- </el-col>-->
+<!-- <el-col :span="12">-->
+<!-- <div class="info-item">-->
+<!-- <span class="info-label">鍛樺伐缂栧彿锛�</span>-->
+<!-- <span class="info-value">{{ form.staffNo || '-' }}</span>-->
+<!-- </div>-->
+<!-- </el-col>-->
+<!-- </el-row>-->
</div>
- <!-- 绂昏亴淇℃伅濉啓鍖哄煙 -->
- <!-- <el-form :model="form" label-width="140px" label-position="top" :rules="rules" ref="formRef" style="margin-top: 20px">
- <el-row :gutter="30">
- <el-col :span="12">
- <el-form-item label="绂昏亴鏃ユ湡锛�" prop="dimissionDate">
- <el-date-picker
- v-model="form.dimissionDate"
- type="date"
- placeholder="璇烽�夋嫨绂昏亴鏃ユ湡"
- value-format="YYYY-MM-DD"
- format="YYYY-MM-DD"
- clearable
- style="width: 100%"
- />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="绂昏亴鍘熷洜锛�" prop="dimissionReason">
- <el-input
- v-model="form.dimissionReason"
- type="textarea"
- :rows="3"
- placeholder="璇疯緭鍏ョ鑱屽師鍥�"
- maxlength="500"
- show-word-limit
- />
- </el-form-item>
- </el-col>
- </el-row>
- </el-form> -->
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="submitForm">纭</el-button>
@@ -160,8 +158,8 @@
<script setup>
import {ref, reactive, toRefs, getCurrentInstance} from "vue";
-import {getStaffJoinInfo, staffJoinAdd, staffJoinUpdate} from "@/api/personnelManagement/onboarding.js";
-import { staffOnJobListPage } from "@/api/personnelManagement/employeeRecord.js";
+import {staffOnJobListPage} from "@/api/personnelManagement/staffOnJob.js";
+import {createStaffLeave, updateStaffLeave} from "@/api/personnelManagement/staffLeave.js";
const { proxy } = getCurrentInstance()
const emit = defineEmits(['close'])
@@ -169,86 +167,80 @@
const operationType = ref('')
const data = reactive({
form: {
- staffNo: "",
- staffName: "",
- sex: "",
- nativePlace: "",
- postJob: "",
- adress: "",
- firstStudy: "",
- profession: "",
- age: 0,
- phone: "",
- emergencyContact: "",
- emergencyContactPhone: "",
- contractTerm: 0,
- contractStartTime: "",
- contractExpireTime: "",
- dimissionDate: "",
- dimissionReason: "",
- staffState: "",
+ staffOnJobId: undefined,
+ reason: "",
+ remark: "",
},
rules: {
- staffName: [{ required: true, message: "璇烽�夋嫨浜哄憳", trigger: "change" }],
- dimissionDate: [{ required: true, message: "璇烽�夋嫨绂昏亴鏃ユ湡", trigger: "change" }],
- dimissionReason: [{ required: true, message: "璇疯緭鍏ョ鑱屽師鍥�", trigger: "blur" }],
+ staffName: [{ required: true, message: "璇烽�夋嫨浜哄憳" }],
+ reason: [{ required: true, message: "璇烽�夋嫨绂昏亴鍘熷洜"}],
},
+ dimissionReasonOptions: [
+ {label: '钖祫寰呴亣', value: 'salary'},
+ {label: '鑱屼笟鍙戝睍', value: 'career_development'},
+ {label: '宸ヤ綔鐜', value: 'work_environment'},
+ {label: '涓汉鍘熷洜', value: 'personal_reason'},
+ {label: '鍏朵粬', value: 'other'},
+ ],
+ currentStaffRecord: {},
});
-const { form, rules } = toRefs(data);
+const { form, rules, dimissionReasonOptions, currentStaffRecord } = toRefs(data);
// 鎵撳紑寮规
const openDialog = (type, row) => {
- getList()
operationType.value = type;
dialogFormVisible.value = true;
if (operationType.value === 'edit') {
- getStaffJoinInfo(row.id).then(res => {
- form.value = {...res.data}
- })
+ currentStaffRecord.value = row
+ form.value.staffOnJobId = row.staffOnJobId
+ form.value.reason = row.reason
+ form.value.remark = row.remark
+ personList.value = [
+ {
+ staffName: row.staffName,
+ id: row.staffOnJobId,
+ }
+ ]
+ } else {
+ getList()
+ }
+}
+
+const handleSelectDimissionReason = (val) => {
+ if (val === 'other') {
+ form.value.remark = ''
}
}
// 鎻愪氦浜у搧琛ㄥ崟
const submitForm = () => {
- // 琛ㄥ崟宸叉敞閲婏紝鐩存帴鎻愪氦锛屼笉杩涜楠岃瘉
- if (!form.value.staffName) {
- proxy.$modal.msgError("璇烽�夋嫨浜哄憳");
- return;
- }
form.value.staffState = 0
- if (operationType.value === "add") {
- staffJoinAdd(form.value).then(res => {
- proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
- closeDia();
- })
- } else {
- staffJoinUpdate(form.value).then(res => {
- proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
- closeDia();
- })
+ if (form.value.reason !== 'other') {
+ form.value.remark = ''
}
+ proxy.$refs["formRef"].validate(valid => {
+ if (valid) {
+ if (operationType.value === "add") {
+ createStaffLeave(form.value).then(res => {
+ proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
+ closeDia();
+ })
+ } else {
+ updateStaffLeave(currentStaffRecord.value.id, form.value).then(res => {
+ proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
+ closeDia();
+ })
+ }
+ }
+ })
+
}
// 鍏抽棴寮规
const closeDia = () => {
// 琛ㄥ崟宸叉敞閲婏紝鎵嬪姩閲嶇疆琛ㄥ崟鏁版嵁
form.value = {
- staffNo: "",
- staffName: "",
- sex: "",
- nativePlace: "",
- postJob: "",
- adress: "",
- firstStudy: "",
- profession: "",
- age: 0,
- phone: "",
- emergencyContact: "",
- emergencyContactPhone: "",
- contractTerm: 0,
- contractStartTime: "",
- contractExpireTime: "",
- dimissionDate: "",
- dimissionReason: "",
- staffState: "",
+ staffOnJobId: undefined,
+ reason: "",
+ remark: "",
};
dialogFormVisible.value = false;
emit('close')
@@ -270,44 +262,11 @@
};
const handleSelect = (val) => {
- let obj = personList.value.find(item => item.staffName === val)
+ let obj = personList.value.find(item => item.id === val)
+ currentStaffRecord.value = {}
if (obj) {
- let {
- sex,
- phone,
- staffNo,
- nativePlace,
- postJob,
- adress,
- firstStudy,
- profession,
- age,
- emergencyContact,
- emergencyContactPhone,
- contractTerm,
- contractStartTime,
- contractExpireTime,
- staffName
- } = obj
// 淇濈暀绂昏亴鏃ユ湡鍜岀鑱屽師鍥狅紝鍙洿鏂板憳宸ヤ俊鎭�
- form.value = {
- ...form.value,
- sex,
- phone,
- staffNo,
- nativePlace,
- postJob,
- adress,
- firstStudy,
- profession,
- age,
- emergencyContact,
- emergencyContactPhone,
- contractTerm,
- contractStartTime,
- contractExpireTime,
- staffName
- }
+ currentStaffRecord.value = obj
}
}
defineExpose({
diff --git a/src/views/personnelManagement/dimission/index.vue b/src/views/personnelManagement/dimission/index.vue
index ae90d99..c6ed705 100644
--- a/src/views/personnelManagement/dimission/index.vue
+++ b/src/views/personnelManagement/dimission/index.vue
@@ -11,22 +11,6 @@
clearable
:prefix-icon="Search"
/>
- <span style="margin-left: 10px;" class="search_title">鍚堝悓寮�濮嬫棩鏈燂細</span>
- <el-date-picker
- v-model="searchForm.entryDateStart"
- type="date"
- placeholder="璇烽�夋嫨鍚堝悓寮�濮嬫棩鏈�"
- size="default"
- @change="(date) => handleDateChange(date,1)"
- />
- <span style="margin-left: 10px;" class="search_title">鍚堝悓缁撴潫鏃ユ湡锛�</span>
- <el-date-picker
- v-model="searchForm.entryDateEnd"
- type="date"
- placeholder="璇烽�夋嫨鍚堝悓缁撴潫鏃ユ湡"
- size="default"
- @change="(date) => handleDateChange(date,2)"
- />
<el-button type="primary" @click="handleQuery" style="margin-left: 10px"
>鎼滅储</el-button
>
@@ -58,9 +42,8 @@
import { Search } from "@element-plus/icons-vue";
import {onMounted, ref} from "vue";
import FormDia from "@/views/personnelManagement/dimission/components/formDia.vue";
-import {staffJoinDel, staffJoinListPage} from "@/api/personnelManagement/onboarding.js";
+import {findStaffLeaveListPage, batchDeleteStaffLeaves} from "@/api/personnelManagement/staffLeave.js";
import {ElMessageBox} from "element-plus";
-import dayjs from "dayjs";
const data = reactive({
searchForm: {
@@ -109,8 +92,12 @@
prop: "nativePlace",
},
{
+ label: "閮ㄩ棬",
+ prop: "deptName",
+ },
+ {
label: "宀椾綅",
- prop: "postJob",
+ prop: "postName",
},
{
label: "鐜颁綇鍧�",
@@ -145,24 +132,11 @@
prop: "emergencyContactPhone",
width:150
},
- // {
- // label: "鍚堝悓骞撮檺",
- // prop: "contractTerm",
- // },
- {
- label: "鍚堝悓寮�濮嬫棩鏈�",
- prop: "contractStartTime",
- width: 120
- },
- {
- label: "鍚堝悓缁撴潫鏃ユ湡",
- prop: "contractEndTime",
- width: 120
- },
{
dataType: "action",
label: "鎿嶄綔",
align: "center",
+ fixed: 'right',
operation: [
{
name: "缂栬緫",
@@ -186,20 +160,6 @@
const { proxy } = getCurrentInstance()
-const handleDateChange = (value,type) => {
- searchForm.value.entryDateEnd = null
- searchForm.value.entryDateStart = null
- if(type === 1){
- if (value) {
- searchForm.value.entryDateStart = dayjs(value).format("YYYY-MM-DD");
- }
- }else{
- if (value) {
- searchForm.value.entryDateEnd = dayjs(value).format("YYYY-MM-DD");
- }
- }
- getList();
-};
// 鏌ヨ鍒楄〃
/** 鎼滅储鎸夐挳鎿嶄綔 */
const handleQuery = () => {
@@ -213,7 +173,7 @@
};
const getList = () => {
tableLoading.value = true;
- staffJoinListPage({...page, ...searchForm.value, staffState: 0}).then(res => {
+ findStaffLeaveListPage({...page, ...searchForm.value}).then(res => {
tableLoading.value = false;
tableData.value = res.data.records
page.total = res.data.total;
@@ -248,7 +208,7 @@
type: "warning",
})
.then(() => {
- staffJoinDel(ids).then((res) => {
+ batchDeleteStaffLeaves(ids).then((res) => {
proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
getList();
});
@@ -265,7 +225,7 @@
type: "warning",
})
.then(() => {
- proxy.download("/staff/staffJoinLeaveRecord/export", {staffState: 0}, "浜哄憳绂昏亴.xlsx");
+ proxy.download("/staff/staffLeave/export", {}, "浜哄憳绂昏亴.xlsx");
})
.catch(() => {
proxy.$modal.msg("宸插彇娑�");
diff --git a/src/views/personnelManagement/employeeRecord/components/NewOrEditFormDia.vue b/src/views/personnelManagement/employeeRecord/components/NewOrEditFormDia.vue
new file mode 100644
index 0000000..1c06a98
--- /dev/null
+++ b/src/views/personnelManagement/employeeRecord/components/NewOrEditFormDia.vue
@@ -0,0 +1,373 @@
+<template>
+ <div>
+ <el-dialog v-model="dialogFormVisible"
+ :title="operationType === 'add' ? '鏂板鍏ヨ亴' : '缂栬緫浜哄憳'"
+ width="70%"
+ @close="closeDia">
+ <el-form :model="form"
+ label-width="140px"
+ label-position="top"
+ :rules="rules"
+ ref="formRef">
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="鍛樺伐缂栧彿锛�"
+ prop="staffNo">
+ <el-input v-model="form.staffNo"
+ placeholder="璇疯緭鍏�"
+ clearable
+ :disabled="operationType !== 'add'" />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="濮撳悕锛�"
+ prop="staffName">
+ <el-input v-model="form.staffName"
+ placeholder="璇疯緭鍏�"
+ clearable />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="鎬у埆锛�"
+ prop="sex">
+ <el-select v-model="form.sex">
+ <el-option label="鐢�"
+ value="鐢�" />
+ <el-option label="濂�"
+ value="濂�" />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鎴风睄浣忓潃锛�"
+ prop="nativePlace">
+ <el-input v-model="form.nativePlace"
+ placeholder="璇疯緭鍏�"
+ clearable />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="宀椾綅锛�"
+ prop="sysPostId">
+ <el-select v-model="form.sysPostId"
+ placeholder="璇烽�夋嫨宀椾綅"
+ clearable>
+ <el-option v-for="item in postOptions"
+ :key="item.postId"
+ :label="item.postName"
+ :value="item.postId"
+ :disabled="item.status === '1'" />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鐜颁綇鍧�锛�"
+ prop="adress">
+ <el-input v-model="form.adress"
+ placeholder="璇疯緭鍏�"
+ clearable />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="閮ㄩ棬锛�"
+ prop="sysDeptId">
+ <el-tree-select v-model="form.sysDeptId"
+ :data="deptOptions"
+ :props="{ value: 'id', label: 'label', children: 'children' }"
+ value-key="id"
+ placeholder="璇烽�夋嫨閮ㄩ棬"
+ check-strictly />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="骞撮緞锛�"
+ prop="age">
+ <el-input-number v-model="form.age"
+ :precision="0"
+ :step="1"
+ style="width: 100%" />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="绗竴瀛﹀巻锛�"
+ prop="firstStudy">
+ <el-input v-model="form.firstStudy"
+ placeholder="璇疯緭鍏�"
+ clearable />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="涓撲笟锛�"
+ prop="profession">
+ <el-input v-model="form.profession"
+ placeholder="璇疯緭鍏�"
+ clearable />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="鑱旂郴鐢佃瘽锛�"
+ prop="phone">
+ <el-input v-model="form.phone"
+ placeholder="璇疯緭鍏�"
+ clearable />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="绱ф�ヨ仈绯讳汉锛�"
+ prop="emergencyContact">
+ <el-input v-model="form.emergencyContact"
+ placeholder="璇疯緭鍏�"
+ clearable />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="绱ф�ヨ仈绯讳汉鑱旂郴鐢佃瘽锛�"
+ prop="emergencyContactPhone">
+ <el-input v-model="form.emergencyContactPhone"
+ placeholder="璇疯緭鍏�"
+ clearable />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鍚堝悓骞撮檺锛�"
+ prop="contractTerm">
+ <el-input-number v-model="form.contractTerm"
+ :precision="0"
+ :step="1"
+ style="width: 100%"
+ :disabled="true" />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="鍚堝悓寮�濮嬫棩鏈燂細"
+ prop="contractStartTime">
+ <el-date-picker v-model="form.contractStartTime"
+ type="date"
+ placeholder="璇烽�夋嫨鏃ユ湡"
+ value-format="YYYY-MM-DD"
+ format="YYYY-MM-DD"
+ clearable
+ style="width: 100%"
+ @change="calculateContractTerm" />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鍚堝悓缁撴潫鏃ユ湡锛�"
+ prop="contractEndTime">
+ <el-date-picker v-model="form.contractEndTime"
+ type="date"
+ placeholder="璇烽�夋嫨鏃ユ湡"
+ value-format="YYYY-MM-DD"
+ format="YYYY-MM-DD"
+ clearable
+ style="width: 100%"
+ @change="calculateContractTerm" />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ </el-form>
+ <template #footer>
+ <div class="dialog-footer">
+ <el-button type="primary"
+ @click="submitForm">纭</el-button>
+ <el-button @click="closeDia">鍙栨秷</el-button>
+ </div>
+ </template>
+ </el-dialog>
+ </div>
+</template>
+
+<script setup>
+ import { ref, onMounted } from "vue";
+ import { findPostOptions } from "@/api/system/post.js";
+ import { listDept } from "@/api/system/dept.js";
+ import {
+ staffOnJobInfo,
+ createStaffOnJob,
+ updateStaffOnJob,
+ } from "@/api/personnelManagement/staffOnJob.js";
+ import { deptTreeSelect } from "@/api/system/user.js";
+ const { proxy } = getCurrentInstance();
+ const emit = defineEmits(["close"]);
+
+ const dialogFormVisible = ref(false);
+ const operationType = ref("");
+ const id = ref(0);
+ const data = reactive({
+ form: {
+ staffNo: "",
+ staffName: "",
+ sex: "",
+ nativePlace: "",
+ postJob: "",
+ adress: "",
+ firstStudy: "",
+ profession: "",
+ age: 0,
+ phone: "",
+ emergencyContact: "",
+ emergencyContactPhone: "",
+ contractTerm: 0,
+ contractStartTime: "",
+ contractEndTime: "",
+ sysPostId: undefined,
+ sysDeptId: undefined,
+ },
+ rules: {
+ staffNo: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ staffName: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ sex: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ nativePlace: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ postJob: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ adress: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ firstStudy: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ profession: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ age: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ phone: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ emergencyContact: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ emergencyContactPhone: [
+ { required: true, message: "璇疯緭鍏�", trigger: "blur" },
+ ],
+ contractTerm: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ contractStartTime: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ contractEndTime: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ sysDeptId: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ },
+ postOptions: [], // 宀椾綅閫夐」
+ deptOptions: [], // 閮ㄩ棬閫夐」
+ });
+ const { form, rules, postOptions, deptOptions } = toRefs(data);
+
+ // 鎵撳紑寮规
+ const openDialog = (type, row) => {
+ operationType.value = type;
+ dialogFormVisible.value = true;
+ if (operationType.value === "edit") {
+ id.value = row.id;
+ staffOnJobInfo(id.value, {}).then(res => {
+ form.value = { ...res.data };
+ if (form.value.sysPostId === 0) {
+ form.value.sysPostId = undefined;
+ }
+ if (form.value.sysDeptId === 0) {
+ form.value.sysDeptId = undefined;
+ }
+ // 缂栬緫鏃朵篃璁$畻涓�娆″悎鍚屽勾闄�
+ calculateContractTerm();
+ });
+ } else {
+ form.value.id = "";
+ }
+ };
+ onMounted(() => {
+ fetchPostOptions();
+ fetchDeptOptions();
+ });
+
+ const fetchPostOptions = () => {
+ findPostOptions().then(res => {
+ postOptions.value = res.data;
+ });
+ };
+
+ // 鏌ヨ閮ㄩ棬鍒楄〃
+ const fetchDeptOptions = () => {
+ deptTreeSelect().then(response => {
+ deptOptions.value = filterDisabledDept(
+ JSON.parse(JSON.stringify(response.data))
+ );
+ });
+ };
+
+ /** 杩囨护绂佺敤鐨勯儴闂� */
+ function filterDisabledDept(deptList) {
+ return deptList.filter(dept => {
+ if (dept.disabled) {
+ return false;
+ }
+ if (dept.children && dept.children.length) {
+ dept.children = filterDisabledDept(dept.children);
+ }
+ return true;
+ });
+ }
+
+ // 鎻愪氦浜у搧琛ㄥ崟
+ const submitForm = () => {
+ if (!form.value.sysPostId) {
+ form.value.sysPostId = undefined;
+ }
+ if (!form.value.sysDeptId) {
+ form.value.sysDeptId = undefined;
+ }
+ proxy.$refs.formRef.validate(valid => {
+ if (valid) {
+ if (operationType.value === "add") {
+ createStaffOnJob(form.value).then(res => {
+ proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
+ closeDia();
+ });
+ } else {
+ updateStaffOnJob(id.value, form.value).then(res => {
+ proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
+ closeDia();
+ });
+ }
+ }
+ });
+ };
+ // 璁$畻鍚堝悓骞撮檺
+ const calculateContractTerm = () => {
+ if (form.value.contractStartTime && form.value.contractEndTime) {
+ const startDate = new Date(form.value.contractStartTime);
+ const endDate = new Date(form.value.contractEndTime);
+
+ if (endDate > startDate) {
+ // 璁$畻骞翠唤宸�
+ const yearDiff = endDate.getFullYear() - startDate.getFullYear();
+ const monthDiff = endDate.getMonth() - startDate.getMonth();
+ const dayDiff = endDate.getDate() - startDate.getDate();
+
+ let years = yearDiff;
+
+ // 濡傛灉缁撴潫鏃ユ湡鐨勬湀鏃ュ皬浜庡紑濮嬫棩鏈熺殑鏈堟棩锛屽垯鍑忓幓1骞�
+ if (monthDiff < 0 || (monthDiff === 0 && dayDiff < 0)) {
+ years = yearDiff - 1;
+ }
+
+ form.value.contractTerm = Math.max(0, years);
+ } else {
+ form.value.contractTerm = 0;
+ }
+ } else {
+ form.value.contractTerm = 0;
+ }
+ };
+
+ // 鍏抽棴寮规
+ const closeDia = () => {
+ proxy.resetForm("formRef");
+ dialogFormVisible.value = false;
+ emit("close");
+ };
+ defineExpose({
+ openDialog,
+ });
+</script>
+
+<style scoped>
+</style>
\ No newline at end of file
diff --git a/src/views/personnelManagement/employeeRecord/components/RenewContract.vue b/src/views/personnelManagement/employeeRecord/components/RenewContract.vue
new file mode 100644
index 0000000..9c2acfc
--- /dev/null
+++ b/src/views/personnelManagement/employeeRecord/components/RenewContract.vue
@@ -0,0 +1,141 @@
+<template>
+ <el-dialog
+ v-model="isShow"
+ title="缁鍚堝悓"
+ width="800px"
+ @close="closeModal"
+ >
+ <el-form :model="form" label-width="140px" label-position="top" :rules="rules" ref="formRef">
+ <el-form-item label="鍚堝悓寮�濮嬫棩鏈燂細" prop="contractStartTime">
+ <el-date-picker
+ v-model="form.contractStartTime"
+ type="date"
+ placeholder="璇烽�夋嫨鏃ユ湡"
+ value-format="YYYY-MM-DD"
+ format="YYYY-MM-DD"
+ clearable
+ style="width: 100%"
+ @change="calculateContractTerm"
+ />
+ </el-form-item>
+ <el-form-item label="鍚堝悓缁撴潫鏃ユ湡锛�" prop="contractEndTime">
+ <el-date-picker
+ v-model="form.contractEndTime"
+ type="date"
+ placeholder="璇烽�夋嫨鏃ユ湡"
+ value-format="YYYY-MM-DD"
+ format="YYYY-MM-DD"
+ clearable
+ style="width: 100%"
+ @change="calculateContractTerm"
+ />
+ </el-form-item>
+ <el-form-item label="鍚堝悓骞撮檺锛�" prop="contractTerm">
+ <el-input-number v-model="form.contractTerm" :precision="0" :step="1" style="width: 100%" :disabled="true"/>
+ </el-form-item>
+ </el-form>
+ <template #footer>
+ <div class="dialog-footer">
+ <el-button type="primary" @click="submitForm">纭</el-button>
+ <el-button @click="closeModal">鍙栨秷</el-button>
+ </div>
+ </template>
+ </el-dialog>
+</template>
+
+<script setup>
+// 缁鍚堝悓
+import { renewContract } from "@/api/personnelManagement/staffOnJob.js";
+import {computed, getCurrentInstance,} from "vue";
+
+const emit = defineEmits(['update:visible', 'completed']);
+
+const data = reactive({
+ form: {
+ contractTerm: 0,
+ contractStartTime: "",
+ contractEndTime: "",
+ },
+ rules: {
+ contractTerm: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ contractStartTime: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ contractEndTime: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ }
+});
+const { form, rules } = toRefs(data);
+let { proxy } = getCurrentInstance()
+
+const props = defineProps({
+ id: {
+ type: Number,
+ default: 0,
+ },
+
+ visible: {
+ type: Boolean,
+ required: true,
+ },
+})
+
+const isShow = computed({
+ get() {
+ return props.visible;
+ },
+ set(val) {
+ emit('update:visible', val);
+ },
+});
+
+// 璁$畻鍚堝悓骞撮檺
+const calculateContractTerm = () => {
+ if (form.value.contractStartTime && form.value.contractEndTime) {
+ const startDate = new Date(form.value.contractStartTime);
+ const endDate = new Date(form.value.contractEndTime);
+
+ if (endDate > startDate) {
+ // 璁$畻骞翠唤宸�
+ const yearDiff = endDate.getFullYear() - startDate.getFullYear();
+ const monthDiff = endDate.getMonth() - startDate.getMonth();
+ const dayDiff = endDate.getDate() - startDate.getDate();
+
+ let years = yearDiff;
+
+ // 濡傛灉缁撴潫鏃ユ湡鐨勬湀鏃ュ皬浜庡紑濮嬫棩鏈熺殑鏈堟棩锛屽垯鍑忓幓1骞�
+ if (monthDiff < 0 || (monthDiff === 0 && dayDiff < 0)) {
+ years = yearDiff - 1;
+ }
+
+ form.value.contractTerm = Math.max(0, years);
+ } else {
+ form.value.contractTerm = 0;
+ }
+ } else {
+ form.value.contractTerm = 0;
+ }
+};
+
+const submitForm = () => {
+ proxy.$refs["formRef"].validate(valid => {
+ if (valid) {
+ renewContract(props.id, form.value).then(res => {
+ if (res.code === 200) {
+ proxy.$modal.msgSuccess("缁鍚堝悓鎴愬姛");
+ emit('completed');
+ closeModal();
+ }
+ })
+ }
+ })
+}
+
+// 鍏抽棴寮规
+const closeModal = () => {
+ // 閲嶇疆琛ㄥ崟鏁版嵁
+ form.value = {
+ contractTerm: 0,
+ contractStartTime: "",
+ contractEndTime: "",
+ };
+ isShow.value = false;
+};
+</script>
diff --git a/src/views/personnelManagement/employeeRecord/components/Show.vue b/src/views/personnelManagement/employeeRecord/components/Show.vue
new file mode 100644
index 0000000..9220d45
--- /dev/null
+++ b/src/views/personnelManagement/employeeRecord/components/Show.vue
@@ -0,0 +1,73 @@
+<template>
+ <div>
+ <el-dialog
+ v-model="dialogFormVisible"
+ title="璇︽儏"
+ width="70%"
+ @close="closeDia"
+ >
+ <PIMTable
+ rowKey="id"
+ :column="tableColumn"
+ :tableData="tableData"
+ :tableLoading="tableLoading"
+ height="600"
+ ></PIMTable>
+ <template #footer>
+ <div class="dialog-footer">
+ <el-button @click="closeDia">鍙栨秷</el-button>
+ </div>
+ </template>
+ </el-dialog>
+ </div>
+</template>
+
+<script setup>
+import {ref} from "vue";
+import {staffOnJobInfo} from "@/api/personnelManagement/staffOnJob.js";
+const { proxy } = getCurrentInstance()
+const emit = defineEmits(['close'])
+
+const dialogFormVisible = ref(false);
+const operationType = ref('')
+const tableColumn = ref([
+ // {
+ // label: "鍚堝悓骞撮檺",
+ // prop: "contractTerm",
+ // },
+ {
+ label: "鍚堝悓寮�濮嬫棩鏈�",
+ prop: "contractStartTime",
+ },
+ {
+ label: "鍚堝悓缁撴潫鏃ユ湡",
+ prop: "contractEndTime",
+ },
+]);
+const tableData = ref([]);
+const tableLoading = ref(false);
+
+// 鎵撳紑寮规
+const openDialog = (type, row) => {
+ operationType.value = type;
+ dialogFormVisible.value = true;
+ if (operationType.value === 'edit') {
+ staffOnJobInfo({staffNo: row.staffNo}).then(res => {
+ tableData.value = res.data
+ })
+ }
+}
+
+// 鍏抽棴寮规
+const closeDia = () => {
+ dialogFormVisible.value = false;
+ emit('close')
+};
+defineExpose({
+ openDialog,
+});
+</script>
+
+<style scoped>
+
+</style>
\ No newline at end of file
diff --git a/src/views/personnelManagement/employeeRecord/components/formDia.vue b/src/views/personnelManagement/employeeRecord/components/formDia.vue
deleted file mode 100644
index c20877d..0000000
--- a/src/views/personnelManagement/employeeRecord/components/formDia.vue
+++ /dev/null
@@ -1,178 +0,0 @@
-<template>
- <div>
- <el-dialog
- v-model="dialogFormVisible"
- title="璇︽儏"
- width="70%"
- @close="closeDia"
- >
- <!-- 鎸夌収鍏ヨ亴鏂板寮圭獥瀛楁灞曠ず鍩虹淇℃伅鍜屽悎鍚屼俊鎭� -->
- <el-descriptions class="detail-descriptions" :column="2" border size="small">
- <el-descriptions-item label="鍛樺伐缂栧彿">
- {{ formData.staffNo || '-' }}
- </el-descriptions-item>
- <el-descriptions-item label="濮撳悕">
- {{ formData.staffName || '-' }}
- </el-descriptions-item>
- <el-descriptions-item label="鎬у埆">
- {{ formData.sex || '-' }}
- </el-descriptions-item>
- <el-descriptions-item label="骞撮緞">
- {{ formData.age || '-' }}
- </el-descriptions-item>
- <el-descriptions-item label="鎴风睄浣忓潃" :span="2">
- {{ formData.nativePlace || '-' }}
- </el-descriptions-item>
- <el-descriptions-item label="鐜颁綇鍧�" :span="2">
- {{ formData.adress || '-' }}
- </el-descriptions-item>
- <el-descriptions-item label="宀椾綅">
- {{ formData.postJob || '-' }}
- </el-descriptions-item>
- <el-descriptions-item label="绗竴瀛﹀巻">
- {{ formData.firstStudy || '-' }}
- </el-descriptions-item>
- <el-descriptions-item label="涓撲笟">
- {{ formData.profession || '-' }}
- </el-descriptions-item>
- <el-descriptions-item label="鑱旂郴鐢佃瘽">
- {{ formData.phone || '-' }}
- </el-descriptions-item>
- <el-descriptions-item label="绱ф�ヨ仈绯讳汉">
- {{ formData.emergencyContact || '-' }}
- </el-descriptions-item>
- <el-descriptions-item label="绱ф�ヨ仈绯讳汉鐢佃瘽">
- {{ formData.emergencyContactPhone || '-' }}
- </el-descriptions-item>
- <el-descriptions-item label="鍚堝悓寮�濮嬫棩鏈�">
- {{ formData.contractStartTime || '-' }}
- </el-descriptions-item>
- <el-descriptions-item label="鍚堝悓缁撴潫鏃ユ湡">
- {{ formData.contractExpireTime || '-' }}
- </el-descriptions-item>
- <el-descriptions-item label="鍚堝悓骞撮檺">
- {{ formattedContractTerm }}
- </el-descriptions-item>
- </el-descriptions>
- <template #footer>
- <div class="dialog-footer">
- <el-button @click="closeDia">鍏抽棴</el-button>
- </div>
- </template>
- </el-dialog>
- </div>
-</template>
-
-<script setup>
-import {ref, reactive, computed} from "vue";
-import dayjs from "dayjs";
-const emit = defineEmits(['close'])
-
-const dialogFormVisible = ref(false);
-const operationType = ref('')
-const formData = reactive({
- staffNo: "",
- staffName: "",
- sex: "",
- identityCard: "",
- nativePlace: "",
- postJob: "",
- adress: "",
- firstStudy: "",
- profession: "",
- age: 0,
- phone: "",
- emergencyContact: "",
- emergencyContactPhone: "",
- dateSelect: "",
- trialStartDate: "",
- trialEndDate: "",
- proSalary: null,
- signDate: "",
- salarySelect: "",
- contractStartTime: "",
- contractExpireTime: "",
- contractTerm: null,
- remark: "",
-});
-
-const formattedContractTerm = computed(() => {
- const value = formData.contractTerm;
- if (value === null || value === undefined || value === "") {
- return "-";
- }
- const numberValue = Number(value);
- if (!isNaN(numberValue)) {
- return `${numberValue}骞碻;
- }
- return value;
-});
-
-const calculatedContractStart = computed(() => {
- const endDate = formData.contractExpireTime;
- const termValue = formData.contractTerm;
- const numberValue = Number(termValue);
- if (!endDate || isNaN(numberValue)) {
- return formData.contractStartTime || "-";
- }
- const start = dayjs(endDate).subtract(numberValue, "year");
- if (!start.isValid()) {
- return formData.contractStartTime || "-";
- }
- return start.format("YYYY-MM-DD");
-});
-
-// 鎵撳紑寮规
-const openDialog = (type, row) => {
- operationType.value = type;
- dialogFormVisible.value = true;
- // 閲嶇疆琛ㄥ崟鏁版嵁
- Object.keys(formData).forEach(key => {
- if (key === 'age') {
- formData[key] = 0;
- } else if (["proSalary", "contractTerm"].includes(key)) {
- formData[key] = null;
- } else {
- formData[key] = "";
- }
- });
-
- if (operationType.value === 'edit' && row) {
- // 鐩存帴浣跨敤 row 鏁版嵁璧嬪��
- Object.assign(formData, row);
- }
-}
-
-// 鍏抽棴寮规
-const closeDia = () => {
- dialogFormVisible.value = false;
- emit('close')
-};
-defineExpose({
- openDialog,
-});
-</script>
-
-<style scoped>
-.detail-descriptions {
- margin-bottom: 16px;
- border-radius: 6px;
- overflow: hidden;
-}
-
-.detail-descriptions :deep(.el-descriptions__cell) {
- padding: 12px 16px !important;
-}
-
-.detail-descriptions :deep(.el-descriptions__label) {
- width: 140px;
- color: #606266;
- background-color: #f7f9fc;
- font-weight: 500;
-}
-
-.detail-descriptions :deep(.el-descriptions__content) {
- color: #303133;
- line-height: 20px;
-}
-</style>
\ No newline at end of file
diff --git a/src/views/personnelManagement/employeeRecord/index.vue b/src/views/personnelManagement/employeeRecord/index.vue
index 5a0d07c..19addfa 100644
--- a/src/views/personnelManagement/employeeRecord/index.vue
+++ b/src/views/personnelManagement/employeeRecord/index.vue
@@ -19,9 +19,9 @@
>
</div>
<div>
-<!-- <el-button type="primary" @click="openForm('add')">鏂板鍏ヨ亴</el-button>-->
+ <el-button type="primary" @click="openFormNewOrEditFormDia('add')">鏂板鍏ヨ亴</el-button>
<el-button @click="handleOut">瀵煎嚭</el-button>
-<!-- <el-button type="danger" plain @click="handleDelete">鍒犻櫎</el-button>-->
+ <el-button type="danger" plain @click="handleDelete">鍒犻櫎</el-button>
</div>
</div>
<div class="table_list">
@@ -37,17 +37,26 @@
:total="page.total"
></PIMTable>
</div>
- <form-dia ref="formDia" @close="handleQuery"></form-dia>
+ <show-form-dia ref="formDia" @close="handleQuery"></show-form-dia>
+ <new-or-edit-form-dia ref="formDiaNewOrEditFormDia" @close="handleQuery"></new-or-edit-form-dia>
+ <renew-contract
+ v-if="isShowRenewContractModal"
+ v-model:visible="isShowRenewContractModal"
+ :id="id"
+ @completed="handleQuery"
+ />
</div>
</template>
<script setup>
import { Search } from "@element-plus/icons-vue";
import {onMounted, ref} from "vue";
-import FormDia from "@/views/personnelManagement/employeeRecord/components/formDia.vue";
import {ElMessageBox} from "element-plus";
-import {staffOnJobListPage} from "@/api/personnelManagement/employeeRecord.js";
+import {batchDeleteStaffOnJobs, staffOnJobListPage} from "@/api/personnelManagement/staffOnJob.js";
import dayjs from "dayjs";
+const NewOrEditFormDia = defineAsyncComponent(() => import("@/views/personnelManagement/employeeRecord/components/NewOrEditFormDia.vue"));
+const ShowFormDia = defineAsyncComponent(() => import( "@/views/personnelManagement/employeeRecord/components/Show.vue"));
+const RenewContract = defineAsyncComponent(() => import( "@/views/personnelManagement/employeeRecord/components/RenewContract.vue"));
const data = reactive({
searchForm: {
@@ -58,6 +67,8 @@
},
});
const { searchForm } = toRefs(data);
+const isShowRenewContractModal = ref(false);
+const id = ref(0);
const tableColumn = ref([
{
label: "鐘舵��",
@@ -97,6 +108,10 @@
{
label: "鎴风睄浣忓潃",
prop: "nativePlace",
+ },
+ {
+ label: "閮ㄩ棬",
+ prop: "deptName",
},
{
label: "宀椾綅",
@@ -154,14 +169,31 @@
label: "鎿嶄綔",
align: "center",
fixed: 'right',
+ width: 180,
operation: [
{
- name: "璇︽儏",
+ name: "缂栬緫",
type: "text",
clickFun: (row) => {
- openForm("edit", row);
+ openFormNewOrEditFormDia("edit", row);
},
},
+ {
+ name: "缁鍚堝悓",
+ type: "text",
+ showHide: row => row.staffState === 1,
+ clickFun: (row) => {
+ isShowRenewContractModal.value = true;
+ id.value = row.id;
+ },
+ },
+ // {
+ // name: "璇︽儏",
+ // type: "text",
+ // clickFun: (row) => {
+ // openForm("edit", row);
+ // },
+ // },
],
},
]);
@@ -174,6 +206,7 @@
total: 0
});
const formDia = ref()
+const formDiaNewOrEditFormDia = ref()
const { proxy } = getCurrentInstance()
const changeDaterange = (value) => {
@@ -200,7 +233,7 @@
tableLoading.value = true;
const params = { ...searchForm.value, ...page };
params.entryDate = undefined
- staffOnJobListPage({...params, staffState: 1}).then(res => {
+ staffOnJobListPage({...params}).then(res => {
tableLoading.value = false;
tableData.value = res.data.records
page.total = res.data.total;
@@ -219,6 +252,37 @@
formDia.value?.openDialog(type, row)
})
};
+const openFormNewOrEditFormDia = (type, row) => {
+ nextTick(() => {
+ formDiaNewOrEditFormDia.value?.openDialog(type, row)
+ })
+};
+
+// 鍒犻櫎
+const handleDelete = () => {
+ let ids = [];
+ if (selectedRows.value.length > 0) {
+ ids = selectedRows.value.map((item) => item.id);
+ } else {
+ proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
+ return;
+ }
+ ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "瀵煎嚭", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ })
+ .then(() => {
+ batchDeleteStaffOnJobs(ids).then((res) => {
+ proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+ getList();
+ });
+ })
+ .catch(() => {
+ proxy.$modal.msg("宸插彇娑�");
+ });
+};
+
// 瀵煎嚭
const handleOut = () => {
ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚鍑猴紝鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
@@ -227,7 +291,7 @@
type: "warning",
})
.then(() => {
- proxy.download("/staff/staffOnJob/export", {staffState: 1}, "鍦ㄨ亴鍛樺伐鍙拌处.xlsx");
+ proxy.download("/staff/staffOnJob/export", {staffState: 1}, "鍛樺伐鍙拌处.xlsx");
})
.catch(() => {
proxy.$modal.msg("宸插彇娑�");
diff --git a/src/views/personnelManagement/monthlyStatistics/components/formDia.vue b/src/views/personnelManagement/monthlyStatistics/components/formDia.vue
new file mode 100644
index 0000000..c67fdd6
--- /dev/null
+++ b/src/views/personnelManagement/monthlyStatistics/components/formDia.vue
@@ -0,0 +1,318 @@
+<template>
+ <el-dialog v-model="dialogVisible"
+ :title="title"
+ width="700px"
+ :close-on-click-modal="false">
+ <el-form ref="formRef"
+ :model="form"
+ :rules="rules"
+ label-width="140px"
+ label-position="top">
+ <el-row :gutter="20">
+ <el-col :span="12">
+ <el-form-item label="缁熻鏈堜唤"
+ prop="payDate">
+ <el-date-picker v-model="form.payDate"
+ type="month"
+ value-format="YYYY-MM"
+ format="YYYY-MM"
+ placeholder="璇烽�夋嫨鏈堜唤"
+ style="width: 100%"
+ :disabled="operationType === 'view'" />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="濮撳悕"
+ prop="staffId">
+ <el-select v-model="form.staffId"
+ placeholder="璇烽�夋嫨鍛樺伐"
+ style="width: 100%"
+ :disabled="operationType === 'view'">
+ <el-option v-for="item in userList"
+ :key="item.id"
+ :label="item.staffName"
+ :value="item.id" />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="20">
+ <el-col :span="12">
+ <el-form-item label="鍩烘湰宸ヨ祫"
+ prop="basicSalary">
+ <el-input v-model="form.basicSalary"
+ type="number"
+ placeholder="璇疯緭鍏ュ熀鏈伐璧�"
+ :disabled="operationType === 'view'" />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="璁′欢宸ヨ祫"
+ prop="pieceworkSalary">
+ <el-input v-model="form.pieceworkSalary"
+ type="number"
+ placeholder="璇疯緭鍏ヨ浠跺伐璧�"
+ :disabled="operationType === 'view'" />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="20">
+ <el-col :span="12">
+ <el-form-item label="璁℃椂宸ヨ祫"
+ prop="hourlySalary">
+ <el-input v-model="form.hourlySalary"
+ type="number"
+ placeholder="璇疯緭鍏ヨ鏃跺伐璧�"
+ :disabled="operationType === 'view'" />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鍏朵粬鏀跺叆"
+ prop="otherIncome">
+ <el-input v-model="form.otherIncome"
+ type="number"
+ placeholder="璇疯緭鍏ュ叾浠栨敹鍏�"
+ :disabled="operationType === 'view'" />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="20">
+ <el-col :span="12">
+ <el-form-item label="绀句繚涓汉"
+ prop="socialSecurityIndividuals">
+ <el-input v-model="form.socialSecurityIndividuals"
+ type="number"
+ placeholder="璇疯緭鍏ョぞ淇濅釜浜�"
+ :disabled="operationType === 'view'" />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鍏Н閲戜釜浜�"
+ prop="providentFundIndividuals">
+ <el-input v-model="form.providentFundIndividuals"
+ type="number"
+ placeholder="璇疯緭鍏ュ叕绉噾涓汉"
+ :disabled="operationType === 'view'" />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="20">
+ <el-col :span="12">
+ <el-form-item label="涓汉鎵�寰楃◣"
+ prop="personalIncomeTax">
+ <el-input v-model="form.personalIncomeTax"
+ type="number"
+ placeholder="璇疯緭鍏ヤ釜浜烘墍寰楃◣"
+ :disabled="operationType === 'view'" />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鍏朵粬鎵f"
+ prop="otherDeductions">
+ <el-input v-model="form.otherDeductions"
+ type="number"
+ placeholder="璇疯緭鍏ュ叾浠栨墸娆�"
+ :disabled="operationType === 'view'" />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="20">
+ <el-col :span="24">
+ <el-form-item label="澶囨敞"
+ prop="remark">
+ <el-input v-model="form.remark"
+ type="textarea"
+ placeholder="璇疯緭鍏ュ娉�"
+ :rows="3"
+ :disabled="operationType === 'view'" />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ </el-form>
+ <template #footer>
+ <span class="dialog-footer">
+ <el-button @click="dialogVisible = false">鍙栨秷</el-button>
+ <el-button type="primary"
+ @click="submitForm"
+ v-if="operationType !== 'view'">
+ 纭畾
+ </el-button>
+ </span>
+ </template>
+ </el-dialog>
+</template>
+
+<script setup>
+ import { ref, reactive, computed, onMounted } from "vue";
+ import { ElMessage } from "element-plus";
+ import {
+ monthlyStatisticsAdd,
+ monthlyStatisticsUpdate,
+ staffOnJobList,
+ } from "@/api/personnelManagement/monthlyStatistics.js";
+
+ const props = defineProps({
+ modelValue: {
+ type: Boolean,
+ default: false,
+ },
+ operationType: {
+ type: String,
+ default: "add",
+ },
+ row: {
+ type: Object,
+ default: () => ({}),
+ },
+ });
+
+ const emit = defineEmits(["update:modelValue", "close"]);
+
+ const dialogVisible = computed({
+ get: () => props.modelValue,
+ set: val => emit("update:modelValue", val),
+ });
+
+ const title = computed(() => {
+ if (props.operationType === "add") return "鏂板钖祫鍙拌处";
+ if (props.operationType === "edit") return "缂栬緫钖祫鍙拌处";
+ return "鏌ョ湅钖祫鍙拌处";
+ });
+
+ const formRef = ref();
+ const form = reactive({
+ id: "",
+ payDate: "",
+ staffId: "",
+ basicSalary: 0,
+ pieceworkSalary: 0,
+ hourlySalary: 0,
+ otherIncome: 0,
+ socialSecurityIndividuals: 0,
+ providentFundIndividuals: 0,
+ personalIncomeTax: 0,
+ otherDeductions: 0,
+ payableWages: 0,
+ deductibleWages: 0,
+ actualWages: 0,
+ remark: "",
+ });
+
+ const rules = {
+ payDate: [{ required: true, message: "璇烽�夋嫨缁熻鏈堜唤", trigger: "change" }],
+ staffId: [{ required: true, message: "璇烽�夋嫨鍛樺伐", trigger: "change" }],
+ basicSalary: [{ required: true, message: "璇疯緭鍏ュ熀鏈伐璧�", trigger: "blur" }],
+ };
+
+ const userList = ref([]);
+
+ const loadUserList = () => {
+ // userListNoPage().then(res => {
+ // userList.value = res.data || [];
+ // });
+ staffOnJobList().then(res => {
+ userList.value = res.data || [];
+ });
+ };
+
+ const openDialog = (type, row) => {
+ // 閲嶇疆琛ㄥ崟
+ Object.assign(form, {
+ id: "",
+ payDate: "",
+ staffId: "",
+ basicSalary: 0,
+ pieceworkSalary: 0,
+ hourlySalary: 0,
+ otherIncome: 0,
+ socialSecurityIndividuals: 0,
+ providentFundIndividuals: 0,
+ personalIncomeTax: 0,
+ otherDeductions: 0,
+ payableWages: 0,
+ deductibleWages: 0,
+ actualWages: 0,
+ remark: "",
+ });
+
+ if (type === "add") {
+ dialogVisible.value = true;
+ } else if (type === "edit" || type === "view") {
+ if (row && row.id) {
+ Object.assign(form, row);
+ dialogVisible.value = true;
+ }
+ }
+ };
+
+ const submitForm = () => {
+ formRef.value.validate(valid => {
+ if (valid) {
+ form.basicSalary = Number(form.basicSalary);
+ form.pieceworkSalary = Number(form.pieceworkSalary);
+ form.hourlySalary = Number(form.hourlySalary);
+ form.otherIncome = Number(form.otherIncome);
+ form.socialSecurityIndividuals = Number(form.socialSecurityIndividuals);
+ form.providentFundIndividuals = Number(form.providentFundIndividuals);
+ form.personalIncomeTax = Number(form.personalIncomeTax);
+ form.otherDeductions = Number(form.otherDeductions);
+
+ // 璁$畻搴斿彂宸ヨ祫銆佸簲鎵e伐璧勫拰瀹炲彂宸ヨ祫
+ const payableWages =
+ form.basicSalary +
+ form.pieceworkSalary +
+ form.hourlySalary +
+ form.otherIncome;
+ const deductibleWages =
+ form.socialSecurityIndividuals +
+ form.providentFundIndividuals +
+ form.personalIncomeTax +
+ form.otherDeductions;
+ const actualWages = payableWages - deductibleWages;
+
+ const submitData = {
+ ...form,
+ payableWages,
+ deductibleWages,
+ actualWages,
+ };
+
+ if (props.operationType === "add") {
+ monthlyStatisticsAdd(submitData).then(res => {
+ if (res.code === 200) {
+ ElMessage.success("鏂板鎴愬姛");
+ dialogVisible.value = false;
+ emit("close");
+ } else {
+ ElMessage.error(res.msg || "鏂板澶辫触");
+ }
+ });
+ } else if (props.operationType === "edit") {
+ monthlyStatisticsUpdate(submitData).then(res => {
+ if (res.code === 200) {
+ ElMessage.success("鏇存柊鎴愬姛");
+ dialogVisible.value = false;
+ emit("close");
+ } else {
+ ElMessage.error(res.msg || "鏇存柊澶辫触");
+ }
+ });
+ }
+ }
+ });
+ };
+
+ onMounted(() => {
+ loadUserList();
+ });
+
+ defineExpose({
+ openDialog,
+ });
+</script>
+
+<style scoped>
+ .dialog-footer {
+ text-align: right;
+ }
+</style>
\ No newline at end of file
diff --git a/src/views/personnelManagement/monthlyStatistics/index.vue b/src/views/personnelManagement/monthlyStatistics/index.vue
new file mode 100644
index 0000000..741a4b7
--- /dev/null
+++ b/src/views/personnelManagement/monthlyStatistics/index.vue
@@ -0,0 +1,303 @@
+<template>
+ <div class="app-container">
+ <div class="search_form">
+ <div>
+ <span class="search_title">濮撳悕锛�</span>
+ <el-input v-model="searchForm.staffName"
+ style="width: 240px"
+ placeholder="璇疯緭鍏ュ鍚嶆悳绱�"
+ @change="handleQuery"
+ clearable
+ :prefix-icon="Search" />
+ <span class="search_title ml10">鏈堜唤锛�</span>
+ <el-date-picker v-model="searchForm.payDateStr"
+ type="month"
+ @change="handleQuery"
+ value-format="YYYY-MM"
+ format="YYYY-MM"
+ placeholder="璇烽�夋嫨鏈堜唤"
+ style="width: 240px"
+ clearable />
+ <el-button type="primary"
+ @click="handleQuery"
+ style="margin-left: 10px">
+ 鎼滅储
+ </el-button>
+ </div>
+ <div>
+ <el-button @click="handleExport"
+ style="margin-right: 10px">瀵煎嚭</el-button>
+ <el-button type="primary"
+ @click="openForm('add')">鏂板鍙拌处</el-button>
+ <el-button type="danger"
+ plain
+ @click="handleDelete">鍒犻櫎</el-button>
+ </div>
+ </div>
+ <div class="table_list">
+ <PIMTable rowKey="id"
+ :column="tableColumn"
+ :tableData="tableData"
+ :page="page"
+ :isSelection="true"
+ @selection-change="handleSelectionChange"
+ :tableLoading="tableLoading"
+ @pagination="pagination"
+ :total="page.total"></PIMTable>
+ </div>
+ <form-dia v-model="dialogVisible"
+ :operation-type="operationType"
+ :row="currentRow"
+ ref="formDia"
+ @close="handleQuery"></form-dia>
+ </div>
+</template>
+
+<script setup>
+ import { Search } from "@element-plus/icons-vue";
+ import {
+ onMounted,
+ ref,
+ reactive,
+ toRefs,
+ getCurrentInstance,
+ nextTick,
+ } from "vue";
+ import { ElMessageBox } from "element-plus";
+ import dayjs from "dayjs";
+ import FormDia from "./components/formDia.vue";
+ import {
+ monthlyStatisticsListPage,
+ monthlyStatisticsDelete,
+ } from "@/api/personnelManagement/monthlyStatistics.js";
+
+ const data = reactive({
+ searchForm: {
+ staffName: "",
+ payDateStr: "",
+ },
+ });
+
+ const { searchForm } = toRefs(data);
+
+ const tableColumn = ref([
+ {
+ label: "鍛樺伐濮撳悕",
+ prop: "staffName",
+ },
+ {
+ label: "閮ㄩ棬",
+ prop: "deptName",
+ width: 140,
+ },
+ {
+ label: "鏈堜唤",
+ prop: "payDate",
+ },
+ {
+ label: "鍩烘湰宸ヨ祫",
+ prop: "basicSalary",
+ },
+ {
+ label: "璁′欢宸ヨ祫",
+ prop: "pieceworkSalary",
+ },
+ {
+ label: "璁℃椂宸ヨ祫",
+ prop: "hourlySalary",
+ },
+ {
+ label: "鍏朵粬鏀跺叆",
+ prop: "otherIncome",
+ },
+ {
+ label: "绀句繚涓汉",
+ prop: "socialSecurityIndividuals",
+ },
+ {
+ label: "鍏Н閲戜釜浜�",
+ prop: "providentFundIndividuals",
+ width: 140,
+ },
+ {
+ label: "宸ヨ祫涓◣",
+ prop: "personalIncomeTax",
+ },
+ {
+ label: "鍏朵粬鏀嚭",
+ prop: "otherDeductions",
+ },
+ {
+ label: "搴斿彂宸ヨ祫",
+ prop: "payableWages",
+ },
+ {
+ label: "搴旀墸宸ヨ祫",
+ prop: "deductibleWages",
+ },
+ {
+ label: "瀹炲彂宸ヨ祫",
+ prop: "actualWages",
+ },
+ {
+ label: "澶囨敞",
+ prop: "remark",
+ width: 150,
+ },
+ {
+ dataType: "action",
+ label: "鎿嶄綔",
+ align: "center",
+ fixed: "right",
+ width: 220,
+ operation: [
+ {
+ name: "缂栬緫",
+ type: "text",
+ clickFun: row => {
+ openForm("edit", row);
+ },
+ },
+ // {
+ // name: "鏌ョ湅",
+ // type: "text",
+ // clickFun: row => {
+ // openForm("view", row);
+ // },
+ // },
+ ],
+ },
+ ]);
+
+ const tableData = ref([]);
+ const selectedRows = ref([]);
+ const tableLoading = ref(false);
+ const page = reactive({
+ current: 1,
+ size: 100,
+ total: 0,
+ });
+
+ const formDia = ref();
+ const dialogVisible = ref(false);
+ const operationType = ref("add");
+ const currentRow = ref({});
+ const { proxy } = getCurrentInstance();
+
+ // 鏌ヨ鍒楄〃
+ /** 鎼滅储鎸夐挳鎿嶄綔 */
+ const handleQuery = () => {
+ page.current = 1;
+ getList();
+ };
+
+ const pagination = obj => {
+ page.current = obj.page;
+ page.size = obj.limit;
+ getList();
+ };
+
+ const getList = () => {
+ tableLoading.value = true;
+ monthlyStatisticsListPage({ ...page, ...searchForm.value })
+ .then(res => {
+ tableLoading.value = false;
+ tableData.value = res.data.records;
+ page.total = res.data.total;
+ })
+ .catch(err => {
+ tableLoading.value = false;
+ });
+ };
+
+ // 琛ㄦ牸閫夋嫨鏁版嵁
+ const handleSelectionChange = selection => {
+ selectedRows.value = selection;
+ };
+
+ // 鎵撳紑寮规
+ const openForm = (type, row) => {
+ operationType.value = type;
+ currentRow.value = row || {};
+ dialogVisible.value = true;
+ nextTick(() => {
+ formDia.value?.openDialog(type, row);
+ });
+ };
+
+ // 鍒犻櫎
+ const handleDelete = () => {
+ let ids = [];
+ if (selectedRows.value.length > 0) {
+ ids = selectedRows.value.map(item => item.id);
+ } else {
+ proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
+ return;
+ }
+ ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "鍒犻櫎", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ })
+ .then(() => {
+ monthlyStatisticsDelete(ids).then(res => {
+ proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+ getList();
+ });
+ })
+ .catch(() => {
+ proxy.$modal.msg("宸插彇娑�");
+ });
+ };
+
+ // 瀵煎嚭
+ const handleExport = () => {
+ ElMessageBox.confirm("鏄惁纭瀵煎嚭浜哄憳钖祫鍙拌处锛�", "瀵煎嚭", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ })
+ .then(() => {
+ proxy.download(
+ "/compensationPerformance/export",
+ { ...searchForm.value, ...page },
+ "浜哄憳钖祫鍙拌处.xlsx"
+ );
+ })
+ .catch(() => {
+ proxy.$modal.msg("宸插彇娑�");
+ });
+ };
+
+ onMounted(() => {
+ getList();
+ });
+</script>
+
+<style scoped>
+ .search_form {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 20px;
+ flex-wrap: wrap;
+ gap: 10px;
+ }
+
+ .search_title {
+ font-weight: 500;
+ margin-right: 5px;
+ }
+
+ .ml10 {
+ margin-left: 10px;
+ }
+
+ .table_list {
+ margin-top: 20px;
+ }
+
+ .dialog-footer {
+ text-align: right;
+ }
+</style>
\ No newline at end of file
diff --git a/src/views/personnelManagement/onboarding/components/formDia.vue b/src/views/personnelManagement/onboarding/components/formDia.vue
deleted file mode 100644
index d775e6b..0000000
--- a/src/views/personnelManagement/onboarding/components/formDia.vue
+++ /dev/null
@@ -1,272 +0,0 @@
-<template>
- <div>
- <el-dialog
- v-model="dialogFormVisible"
- :title="operationType === 'add' ? '鏂板鍏ヨ亴' : '缂栬緫浜哄憳'"
- width="70%"
- @close="closeDia"
- >
- <el-form :model="form" label-width="140px" label-position="top" :rules="rules" ref="formRef">
- <el-row :gutter="30">
- <el-col :span="12">
- <el-form-item label="鍛樺伐缂栧彿锛�" prop="staffNo">
- <el-input v-model="form.staffNo" placeholder="璇疯緭鍏�" clearable :disabled="operationType !== 'add'"/>
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="濮撳悕锛�" prop="staffName">
- <el-input v-model="form.staffName" placeholder="璇疯緭鍏�" clearable/>
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="30">
- <el-col :span="12">
- <el-form-item label="鎬у埆锛�" prop="sex">
- <el-select v-model="form.sex">
- <el-option label="鐢�" value="鐢�" />
- <el-option label="濂�" value="濂�" />
- </el-select>
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="鎴风睄浣忓潃锛�" prop="nativePlace">
- <el-input v-model="form.nativePlace" placeholder="璇疯緭鍏�" clearable/>
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="30">
- <el-col :span="12">
- <el-form-item label="宀椾綅锛�" prop="postJob">
- <el-input v-model="form.postJob" placeholder="璇疯緭鍏�" clearable/>
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="鐜颁綇鍧�锛�" prop="adress">
- <el-input v-model="form.adress" placeholder="璇疯緭鍏�" clearable/>
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="30">
- <el-col :span="12">
- <el-form-item label="绗竴瀛﹀巻锛�" prop="firstStudy">
- <el-input v-model="form.firstStudy" placeholder="璇疯緭鍏�" clearable/>
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="涓撲笟锛�" prop="profession">
- <el-input v-model="form.profession" placeholder="璇疯緭鍏�" clearable/>
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="30">
- <el-col :span="12">
- <el-form-item label="骞撮緞锛�" prop="age">
- <el-input-number v-model="form.age" :precision="0" :step="1" style="width: 100%"/>
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="30">
- <el-col :span="12">
- <el-form-item label="鑱旂郴鐢佃瘽锛�" prop="phone">
- <el-input v-model="form.phone" placeholder="璇疯緭鍏�" clearable/>
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="绱ф�ヨ仈绯讳汉锛�" prop="emergencyContact">
- <el-input v-model="form.emergencyContact" placeholder="璇疯緭鍏�" clearable/>
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="30">
- <el-col :span="12">
- <el-form-item label="绱ф�ヨ仈绯讳汉鑱旂郴鐢佃瘽锛�" prop="emergencyContactPhone">
- <el-input v-model="form.emergencyContactPhone" placeholder="璇疯緭鍏�" clearable/>
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="鍚堝悓骞撮檺锛�" prop="contractTerm">
- <el-input-number v-model="form.contractTerm" :precision="0" :step="1" style="width: 100%" :disabled="true"/>
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="30">
- <el-col :span="12">
- <el-form-item label="鍚堝悓寮�濮嬫棩鏈燂細" prop="contractStartTime">
- <el-date-picker
- v-model="form.contractStartTime"
- type="date"
- placeholder="璇烽�夋嫨鏃ユ湡"
- value-format="YYYY-MM-DD"
- format="YYYY-MM-DD"
- clearable
- style="width: 100%"
- @change="calculateContractTerm"
- />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="鍚堝悓缁撴潫鏃ユ湡锛�" prop="contractEndTime">
- <el-date-picker
- v-model="form.contractEndTime"
- type="date"
- placeholder="璇烽�夋嫨鏃ユ湡"
- value-format="YYYY-MM-DD"
- format="YYYY-MM-DD"
- clearable
- style="width: 100%"
- @change="calculateContractTerm"
- />
- </el-form-item>
- </el-col>
- </el-row>
- </el-form>
- <template #footer>
- <div class="dialog-footer">
- <el-button type="primary" @click="submitForm">纭</el-button>
- <el-button @click="closeDia">鍙栨秷</el-button>
- </div>
- </template>
- </el-dialog>
- </div>
-</template>
-
-<script setup>
-import {ref, reactive, toRefs, getCurrentInstance} from "vue";
-import {getStaffJoinInfo, staffJoinAdd, staffJoinUpdate} from "@/api/personnelManagement/onboarding.js";
-const { proxy } = getCurrentInstance()
-const emit = defineEmits(['close'])
-
-const dialogFormVisible = ref(false);
-const operationType = ref('')
-const data = reactive({
- form: {
- staffNo: "",
- staffName: "",
- sex: "",
- nativePlace: "",
- postJob: "",
- adress: "",
- firstStudy: "",
- profession: "",
- age: 0,
- phone: "",
- emergencyContact: "",
- emergencyContactPhone: "",
- contractTerm: 0,
- contractStartTime: "",
- contractEndTime: "",
- staffState: "",
- },
- rules: {
- staffNo: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" },],
- staffName: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- sex: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- nativePlace: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- postJob: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- adress: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- firstStudy: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- profession: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- age: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- phone: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- emergencyContact: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- emergencyContactPhone: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- contractTerm: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- contractStartTime: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- contractEndTime: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- },
-});
-const { form, rules } = toRefs(data);
-
-// 鎵撳紑寮规
-const openDialog = (type, row) => {
- operationType.value = type;
- dialogFormVisible.value = true;
- if (operationType.value === 'edit') {
- getStaffJoinInfo(row.id).then(res => {
- form.value = {...res.data}
- // 缂栬緫鏃朵篃璁$畻涓�娆″悎鍚屽勾闄�
- calculateContractTerm();
- })
- } else {
- // 鏂板鏃堕噸缃〃鍗�
- form.value = {
- staffNo: "",
- staffName: "",
- sex: "",
- nativePlace: "",
- postJob: "",
- adress: "",
- firstStudy: "",
- profession: "",
- age: 0,
- phone: "",
- emergencyContact: "",
- emergencyContactPhone: "",
- contractTerm: 0,
- contractStartTime: "",
- contractEndTime: "",
- staffState: "",
- };
- }
-}
-// 鎻愪氦浜у搧琛ㄥ崟
-const submitForm = () => {
- proxy.$refs.formRef.validate(valid => {
- if (valid) {
- form.value.staffState = 1
- if (operationType.value === "add") {
- staffJoinAdd(form.value).then(res => {
- proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
- closeDia();
- })
- } else {
- staffJoinUpdate(form.value).then(res => {
- proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
- closeDia();
- })
- }
- }
- })
-}
-// 璁$畻鍚堝悓骞撮檺
-const calculateContractTerm = () => {
- if (form.value.contractStartTime && form.value.contractEndTime) {
- const startDate = new Date(form.value.contractStartTime);
- const endDate = new Date(form.value.contractEndTime);
-
- if (endDate >= startDate) {
- // 璁$畻骞翠唤宸�
- const yearDiff = endDate.getFullYear() - startDate.getFullYear();
- const monthDiff = endDate.getMonth() - startDate.getMonth();
- const dayDiff = endDate.getDate() - startDate.getDate();
-
- let years = yearDiff;
-
- // 濡傛灉缁撴潫鏃ユ湡鐨勬湀鏃ュ皬浜庡紑濮嬫棩鏈熺殑鏈堟棩锛屽垯鍑忓幓1骞�
- if (monthDiff < 0 || (monthDiff === 0 && dayDiff < 0)) {
- years = yearDiff - 1;
- }
-
- form.value.contractTerm = Math.max(0, years);
- } else {
- form.value.contractTerm = 0;
- }
- } else {
- form.value.contractTerm = 0;
- }
-};
-
-// 鍏抽棴寮规
-const closeDia = () => {
- proxy.resetForm("formRef");
- dialogFormVisible.value = false;
- emit('close')
-};
-defineExpose({
- openDialog,
-});
-</script>
-
-<style scoped>
-
-</style>
\ No newline at end of file
diff --git a/src/views/personnelManagement/onboarding/components/formDiaXJHT.vue b/src/views/personnelManagement/onboarding/components/formDiaXJHT.vue
deleted file mode 100644
index 6b70aef..0000000
--- a/src/views/personnelManagement/onboarding/components/formDiaXJHT.vue
+++ /dev/null
@@ -1,427 +0,0 @@
-<template>
- <div>
- <el-dialog
- v-model="dialogFormVisible"
- :title="operationType === 'add' ? '鏂板鍏ヨ亴' : '缂栬緫浜哄憳'"
- width="70%"
- @close="closeDia"
- >
- <el-form :model="form" label-width="140px" label-position="top" :rules="rules" ref="formRef">
- <el-row :gutter="30">
- <el-col :span="12">
- <el-form-item label="鍛樺伐缂栧彿锛�" prop="staffNo">
- <el-input v-model="form.staffNo" placeholder="璇疯緭鍏�" clearable :disabled="operationType !== 'add'"/>
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="濮撳悕锛�" prop="staffName">
- <el-input v-model="form.staffName" placeholder="璇疯緭鍏�" clearable/>
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="30">
- <el-col :span="12">
- <el-form-item label="鎬у埆锛�" prop="sex">
- <el-select v-model="form.sex">
- <el-option label="鐢�" value="鐢�" />
- <el-option label="濂�" value="濂�" />
- </el-select>
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="鎴风睄浣忓潃锛�" prop="nativePlace">
- <el-input v-model="form.nativePlace" placeholder="璇疯緭鍏�" clearable/>
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="30">
- <el-col :span="12">
- <el-form-item label="宀椾綅锛�" prop="postJob">
- <el-input v-model="form.postJob" placeholder="璇疯緭鍏�" clearable/>
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="鐜颁綇鍧�锛�" prop="adress">
- <el-input v-model="form.adress" placeholder="璇疯緭鍏�" clearable/>
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="30">
- <el-col :span="12">
- <el-form-item label="绗竴瀛﹀巻锛�" prop="firstStudy">
- <el-input v-model="form.firstStudy" placeholder="璇疯緭鍏�" clearable/>
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="涓撲笟锛�" prop="profession">
- <el-input v-model="form.profession" placeholder="璇疯緭鍏�" clearable/>
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="30">
- <el-col :span="12">
- <el-form-item label="韬唤璇佸彿锛�" prop="identityCard">
- <el-input v-model="form.identityCard" placeholder="璇疯緭鍏ヨ韩浠借瘉鍙风爜" clearable maxlength="18" />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="骞撮緞锛�" prop="age">
- <el-input-number v-model="form.age" :precision="0" :step="1" style="width: 100%"/>
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="30">
- <el-col :span="12">
- <el-form-item label="鑱旂郴鐢佃瘽锛�" prop="phone">
- <el-input v-model="form.phone" placeholder="璇疯緭鍏�" clearable/>
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="绱ф�ヨ仈绯讳汉锛�" prop="emergencyContact">
- <el-input v-model="form.emergencyContact" placeholder="璇疯緭鍏�" clearable/>
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="30">
- <el-col :span="12">
- <el-form-item label="绱ф�ヨ仈绯讳汉鑱旂郴鐢佃瘽锛�" prop="emergencyContactPhone">
- <el-input v-model="form.emergencyContactPhone" placeholder="璇疯緭鍏�" clearable/>
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="鍚堝悓绛捐鏃ユ湡锛�" prop="signDate">
- <el-date-picker
- v-model="form.signDate"
- type="date"
- placeholder="璇烽�夋嫨鏃ユ湡"
- value-format="YYYY-MM-DD"
- format="YYYY-MM-DD"
- clearable
- style="width: 100%"
- />
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="30">
- <el-col :span="24">
- <el-form-item label="鍔冲姩鍚堝悓鏈熼檺閫夋嫨锛�" prop="dateSelect">
- <el-radio-group v-model="form.dateSelect">
- <el-radio :value="'A'">
- A銆佹湁鍥哄畾鏈熼檺
- </el-radio>
- <el-radio :value="'B'">
- B銆佹棤鍥哄畾鏈熼檺
- </el-radio>
- <el-radio :value="'C'">
- C銆佷互瀹屾垚涓�瀹氬伐浣滀换鍔′负鏈熼檺
- </el-radio>
- </el-radio-group>
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="30" v-if="showProbationDates">
- <el-col :span="12">
- <el-form-item label="璇曠敤鏈熷紑濮嬫棩鏈燂細" prop="trialStartDate">
- <el-date-picker
- v-model="form.trialStartDate"
- type="date"
- placeholder="璇烽�夋嫨鏃ユ湡"
- value-format="YYYY-MM-DD"
- format="YYYY-MM-DD"
- clearable
- style="width: 100%"
- />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="璇曠敤鏈熺粨鏉熸棩鏈燂細" prop="trialEndDate">
- <el-date-picker
- v-model="form.trialEndDate"
- type="date"
- placeholder="璇烽�夋嫨鏃ユ湡"
- value-format="YYYY-MM-DD"
- format="YYYY-MM-DD"
- clearable
- style="width: 100%"
- />
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="30">
- <el-col :span="12">
- <el-form-item label="鍚堝悓骞撮檺锛�" prop="contractTerm">
- <el-input-number v-model="form.contractTerm" :precision="0" :step="1" style="width: 100%" :disabled="true"/>
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="30">
- <el-col :span="12">
- <el-form-item label="鍚堝悓寮�濮嬫棩鏈燂細" prop="contractStartTime">
- <el-date-picker
- v-model="form.contractStartTime"
- type="date"
- placeholder="璇烽�夋嫨鏃ユ湡"
- value-format="YYYY-MM-DD"
- format="YYYY-MM-DD"
- clearable
- style="width: 100%"
- @change="calculateContractTerm"
- />
- </el-form-item>
- </el-col>
- <el-col :span="12" v-if="showContractEnd">
- <el-form-item label="鍚堝悓缁撴潫鏃ユ湡锛�" prop="contractEndTime">
- <el-date-picker
- v-model="form.contractEndTime"
- type="date"
- placeholder="璇烽�夋嫨鏃ユ湡"
- value-format="YYYY-MM-DD"
- format="YYYY-MM-DD"
- clearable
- style="width: 100%"
- @change="calculateContractTerm"
- />
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="30">
- <el-col :span="12">
- <el-form-item label="璇曠敤鏈熷伐璧勶細" prop="proSalary">
- <el-input-number placeholder="璇疯緭鍏ヨ瘯鐢ㄦ湡宸ヨ祫" :precision="2"
- :step="100"
- :min="0" v-model="form.proSalary" style="width: 100%"/>
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="30">
- <el-col :span="24">
- <el-form-item label="宸ヨ祫鎶ラ叕锛�" prop="salarySelect">
- <el-radio-group v-model="form.salarySelect" class="salary-radio-group">
- <el-radio :value="'A'" class="salary-radio-item">
- A銆佷箼鏂圭殑宸ヨ祫鎶ラ叕鎸夌収鐢叉柟渚濇硶鍒跺畾鐨勮绔犲埗搴︿腑鐨勫唴閮ㄥ伐璧勫垎閰嶅姙娉曠‘瀹氾紝鏍规嵁涔欐柟鐨勫伐浣滃矖浣嶇‘瀹氬叾姣忔湀宸ヨ祫銆�
- </el-radio>
- <el-radio :value="'B'" class="salary-radio-item">
- B銆佺敳鏂瑰涔欐柟瀹炶鍩烘湰宸ヨ祫鍜岀哗鏁堝伐璧勭浉缁撳悎鐨勫唴閮ㄥ伐璧勫垎閰嶅姙娉曪紝涔欐柟鐨勬敹鍏ュ寘鎷熀鏈伐璧勩�佽椁愩�佷氦閫氥�佺敓娲讳綇瀹跨瓑鍚勯」琛ュ姪锛屽鏈夊彉鍔ㄦ牴鎹唴閮ㄥ伐璧勫垎閰嶅姙娉曡皟鏁村叾宸ヨ祫锛涚哗鏁堝伐璧勬牴鎹箼鏂圭殑宸ヤ綔涓氱哗銆佸姵鍔ㄦ垚鏋滃拰瀹為檯璐$尞鎸夌収鍐呴儴鍒嗛厤鍔炴硶鑰冩牳纭畾銆�
- </el-radio>
- <el-radio :value="'C'" class="salary-radio-item">
- C銆佺敳鏂瑰疄琛岃浠跺伐璧勫埗锛屼互鐢叉柟鎺ュ埌璁㈠崟鍙婂叕鍙哥敓浜ц鍒掞紝鎸夌収瀹氶鍜岃浠跺崟浠凤紝鏍规嵁涔欐柟瀹屾垚鐨勪笟缁╋紝鎸夋椂瓒抽鏀粯涔欐柟鐨勫伐璧勬姤閰��
- </el-radio>
- </el-radio-group>
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="30">
- <el-col :span="12">
- <el-form-item label="绂忓埄寰呴亣锛�" prop="remark">
- <el-input v-model="form.remark" placeholder="璇疯緭鍏�" clearable/>
- </el-form-item>
- </el-col>
- </el-row>
- </el-form>
- <template #footer>
- <div class="dialog-footer">
- <el-button type="primary" @click="submitForm">纭</el-button>
- <el-button @click="closeDia">鍙栨秷</el-button>
- </div>
- </template>
- </el-dialog>
- </div>
-</template>
-
-<script setup>
-import {ref, reactive, toRefs, getCurrentInstance, computed, watch} from "vue";
-import {getStaffJoinInfo, staffJoinAdd, staffJoinUpdate} from "@/api/personnelManagement/onboarding.js";
-const { proxy } = getCurrentInstance()
-const emit = defineEmits(['close'])
-
-const dialogFormVisible = ref(false);
-const operationType = ref('')
-const data = reactive({
- form: {
- staffNo: "",
- staffName: "",
- sex: "",
- identityCard: "",
- nativePlace: "",
- postJob: "",
- adress: "",
- firstStudy: "",
- profession: "",
- age: 0,
- phone: "",
- emergencyContact: "",
- emergencyContactPhone: "",
- dateSelect: "",
- trialStartDate: "",
- trialEndDate: "",
- proSalary: null,
- signDate: "",
- salarySelect: "",
- contractTerm: 0,
- contractStartTime: "",
- contractEndTime: "",
- staffState: "",
- },
- rules: {
- staffNo: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" },],
- staffName: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- sex: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- identityCard: [{ required: true, message: "璇疯緭鍏ヨ韩浠借瘉鍙风爜", trigger: "blur" }],
- nativePlace: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- postJob: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- adress: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- firstStudy: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- profession: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- age: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- phone: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- emergencyContact: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- remark: [{ required: false, message: "璇疯緭鍏�", trigger: "blur" }],
- dateSelect: [{ required: true, message: "璇烽�夋嫨鍔冲姩鍚堝悓鏈熼檺", trigger: "change" }],
- trialStartDate: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
- trialEndDate: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
- signDate: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
- salarySelect: [{ required: true, message: "璇烽�夋嫨宸ヨ祫鎶ラ叕鏂瑰紡", trigger: "change" }],
- contractTerm: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- contractStartTime: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- contractEndTime: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- },
-});
-const { form, rules } = toRefs(data);
-
-const showContractEnd = computed(() => form.value.dateSelect === "A");
-const showProbationDates = computed(() => form.value.dateSelect === "A" || form.value.dateSelect === "B");
-
-watch(() => form.value.dateSelect, (type) => {
- if (type !== "A") {
- form.value.contractEndTime = "";
- }
-
- if (type === "C") {
- form.value.signDate = "";
- form.value.trialEndDate = "";
- form.value.proSalary = null;
- }
-}, { immediate: true });
-
-// 鎵撳紑寮规
-const openDialog = (type, row) => {
- operationType.value = type;
- dialogFormVisible.value = true;
- if (operationType.value === 'edit') {
- getStaffJoinInfo(row.id).then(res => {
- form.value = {...res.data}
- // 缂栬緫鏃朵篃璁$畻涓�娆″悎鍚屽勾闄�
- calculateContractTerm();
- })
- } else if (operationType.value === 'add') {
- // 鏂板鏃堕噸缃〃鍗曪紝娓呴櫎 id
- proxy.resetForm("formRef");
- form.value = {
- staffNo: "",
- staffName: "",
- sex: "",
- identityCard: "",
- nativePlace: "",
- postJob: "",
- adress: "",
- firstStudy: "",
- profession: "",
- age: 0,
- phone: "",
- emergencyContact: "",
- emergencyContactPhone: "",
- dateSelect: "",
- trialStartDate: "",
- trialEndDate: "",
- proSalary: null,
- signDate: "",
- salarySelect: "",
- contractTerm: 0,
- contractStartTime: "",
- contractEndTime: "",
- staffState: "",
- };
- // 纭繚娓呴櫎 id
- if (form.value.id !== undefined) {
- delete form.value.id;
- }
- }
-}
-// 鎻愪氦浜у搧琛ㄥ崟
-const submitForm = () => {
- proxy.$refs.formRef.validate(valid => {
- if (valid) {
- form.value.staffState = 1
- if (operationType.value === "add") {
- staffJoinAdd(form.value).then(res => {
- proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
- closeDia();
- })
- } else {
- staffJoinUpdate(form.value).then(res => {
- proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
- closeDia();
- })
- }
- }
- })
-}
-// 璁$畻鍚堝悓骞撮檺
-const calculateContractTerm = () => {
- if (form.value.contractStartTime && form.value.contractEndTime) {
- const startDate = new Date(form.value.contractStartTime);
- const endDate = new Date(form.value.contractEndTime);
-
- if (endDate > startDate) {
- // 璁$畻骞翠唤宸�
- const yearDiff = endDate.getFullYear() - startDate.getFullYear();
- const monthDiff = endDate.getMonth() - startDate.getMonth();
- const dayDiff = endDate.getDate() - startDate.getDate();
-
- let years = yearDiff;
-
- // 濡傛灉缁撴潫鏃ユ湡鐨勬湀鏃ュ皬浜庡紑濮嬫棩鏈熺殑鏈堟棩锛屽垯鍑忓幓1骞�
- if (monthDiff < 0 || (monthDiff === 0 && dayDiff < 0)) {
- years = yearDiff - 1;
- }
-
- form.value.contractTerm = Math.max(0, years);
- } else {
- form.value.contractTerm = 0;
- }
- } else {
- form.value.contractTerm = 0;
- }
-};
-
-// 鍏抽棴寮规
-const closeDia = () => {
- proxy.resetForm("formRef");
- dialogFormVisible.value = false;
- emit('close')
-};
-defineExpose({
- openDialog,
-});
-</script>
-
-<style scoped>
-.salary-radio-group {
- display: flex;
- gap: 12px;
-}
-
-.salary-radio-item {
- white-space: normal;
- word-wrap: break-word;
- line-height: 1.6;
- align-items: flex-start;
-}
-
-.salary-radio-item :deep(.el-radio__label) {
- white-space: normal;
- word-wrap: break-word;
- line-height: 1.6;
- padding-left: 8px;
-}
-</style>
\ No newline at end of file
diff --git a/src/views/personnelManagement/onboarding/index.vue b/src/views/personnelManagement/onboarding/index.vue
deleted file mode 100644
index 9151a6c..0000000
--- a/src/views/personnelManagement/onboarding/index.vue
+++ /dev/null
@@ -1,280 +0,0 @@
-<template>
- <div class="app-container">
- <div class="search_form">
- <div>
- <span class="search_title">濮撳悕锛�</span>
- <el-input
- v-model="searchForm.staffName"
- style="width: 240px"
- placeholder="璇疯緭鍏ュ鍚嶆悳绱�"
- @change="handleQuery"
- clearable
- :prefix-icon="Search"
- />
- <span style="margin-left: 10px;" class="search_title">鍚堝悓寮�濮嬫棩鏈燂細</span>
- <el-date-picker
- v-model="searchForm.entryDateStart"
- type="date"
- placeholder="璇烽�夋嫨鍚堝悓寮�濮嬫棩鏈�"
- size="default"
- @change="(date) => handleDateChange(date,1)"
- />
- <span style="margin-left: 10px;" class="search_title">鍚堝悓缁撴潫鏃ユ湡锛�</span>
- <el-date-picker
- v-model="searchForm.entryDateEnd"
- type="date"
- placeholder="璇烽�夋嫨鍚堝悓缁撴潫鏃ユ湡"
- size="default"
- @change="(date) => handleDateChange(date,2)"
- />
- <el-button type="primary" @click="handleQuery" style="margin-left: 10px"
- >鎼滅储</el-button
- >
- </div>
- <div>
- <el-button type="primary" @click="openForm('add')">鏂板鍏ヨ亴</el-button>
- <el-button @click="handleOut">瀵煎嚭</el-button>
- <el-button type="danger" plain @click="handleDelete">鍒犻櫎</el-button>
- </div>
- </div>
- <div class="table_list">
- <PIMTable
- rowKey="id"
- :column="tableColumn"
- :tableData="tableData"
- :page="page"
- :isSelection="true"
- @selection-change="handleSelectionChange"
- :tableLoading="tableLoading"
- @pagination="pagination"
- :total="page.total"
- ></PIMTable>
- </div>
- <form-dia ref="formDia" @close="handleQuery"></form-dia>
- </div>
-</template>
-
-<script setup>
-import { Search } from "@element-plus/icons-vue";
-import {onMounted, ref} from "vue";
-import FormDia from "@/views/personnelManagement/onboarding/components/formDia.vue";
-// import FormDia from "@/views/personnelManagement/onboarding/components/formDiaXJHT.vue"; // 鏂扮枂椋熷搧鍏徃鐢ㄧ殑琛ㄥ崟
-import {staffJoinDel, staffJoinListPage} from "@/api/personnelManagement/onboarding.js";
-import {ElMessageBox} from "element-plus";
-import dayjs from "dayjs";
-
-const data = reactive({
- searchForm: {
- staffName: "",
- },
-});
-const { searchForm } = toRefs(data);
-const tableColumn = ref([
- {
- label: "鐘舵��",
- prop: "staffState",
- dataType: "tag",
- formatData: (params) => {
- if (params == 0) {
- return "绂昏亴";
- } else if (params == 1) {
- return "鍏ヨ亴";
- } else {
- return null;
- }
- },
- formatType: (params) => {
- if (params == 0) {
- return "danger";
- } else if (params == 1) {
- return "primary";
- } else {
- return null;
- }
- },
- },
- {
- label: "鍛樺伐缂栧彿",
- prop: "staffNo",
- },
- {
- label: "濮撳悕",
- prop: "staffName",
- },
- {
- label: "鎬у埆",
- prop: "sex",
- },
- {
- label: "鎴风睄浣忓潃",
- prop: "nativePlace",
- },
- {
- label: "宀椾綅",
- prop: "postJob",
- },
- {
- label: "鐜颁綇鍧�",
- prop: "adress",
- width:200
- },
- {
- label: "绗竴瀛﹀巻",
- prop: "firstStudy",
- },
- {
- label: "涓撲笟",
- prop: "profession",
- width:100
- },
- {
- label: "骞撮緞",
- prop: "age",
- },
- {
- label: "鑱旂郴鐢佃瘽",
- prop: "phone",
- width:150
- },
- {
- label: "绱ф�ヨ仈绯讳汉",
- prop: "emergencyContact",
- width: 120
- },
- {
- label: "鑱旂郴鐢佃瘽",
- prop: "emergencyContactPhone",
- width:150
- },
- // {
- // label: "鍚堝悓骞撮檺",
- // prop: "contractTerm",
- // },
- {
- label: "鍚堝悓寮�濮嬫棩鏈�",
- prop: "contractStartTime",
- width: 120
- },
- {
- label: "鍚堝悓缁撴潫鏃ユ湡",
- prop: "contractEndTime",
- width: 120
- },
- {
- dataType: "action",
- label: "鎿嶄綔",
- align: "center",
- fixed: 'right',
- operation: [
- {
- name: "缂栬緫",
- type: "text",
- clickFun: (row) => {
- openForm("edit", row);
- },
- },
- ],
- },
-]);
-const tableData = ref([]);
-const selectedRows = ref([]);
-const tableLoading = ref(false);
-const page = reactive({
- current: 1,
- size: 100,
- total: 0,
-});
-const formDia = ref()
-const { proxy } = getCurrentInstance()
-
-const handleDateChange = (value,type) => {
- searchForm.value.entryDateEnd = null
- searchForm.value.entryDateStart = null
- if(type === 1){
- if (value) {
- searchForm.value.entryDateStart = dayjs(value).format("YYYY-MM-DD");
- }
- }else{
- if (value) {
- searchForm.value.entryDateEnd = dayjs(value).format("YYYY-MM-DD");
- }
- }
- getList();
-};
-// 鏌ヨ鍒楄〃
-/** 鎼滅储鎸夐挳鎿嶄綔 */
-const handleQuery = () => {
- page.current = 1;
- getList();
-};
-const pagination = (obj) => {
- page.current = obj.page;
- page.size = obj.limit;
- getList();
-};
-const getList = () => {
- tableLoading.value = true;
- staffJoinListPage({...page, ...searchForm.value, staffState: 1}).then(res => {
- tableLoading.value = false;
- tableData.value = res.data.records
- page.total = res.data.total;
- }).catch(err => {
- tableLoading.value = false;
- })
-};
-// 琛ㄦ牸閫夋嫨鏁版嵁
-const handleSelectionChange = (selection) => {
- selectedRows.value = selection;
-};
-
-// 鎵撳紑寮规
-const openForm = (type, row) => {
- nextTick(() => {
- formDia.value?.openDialog(type, row)
- })
-};
-
-// 鍒犻櫎
-const handleDelete = () => {
- let ids = [];
- if (selectedRows.value.length > 0) {
- ids = selectedRows.value.map((item) => item.id);
- } else {
- proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
- return;
- }
- ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "瀵煎嚭", {
- confirmButtonText: "纭",
- cancelButtonText: "鍙栨秷",
- type: "warning",
- })
- .then(() => {
- staffJoinDel(ids).then((res) => {
- proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
- getList();
- });
- })
- .catch(() => {
- proxy.$modal.msg("宸插彇娑�");
- });
-};
-// 瀵煎嚭
-const handleOut = () => {
- ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚鍑猴紝鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
- confirmButtonText: "纭",
- cancelButtonText: "鍙栨秷",
- type: "warning",
- })
- .then(() => {
- proxy.download("/staff/staffJoinLeaveRecord/export", {staffState: 1}, "浜哄憳鍏ヨ亴.xlsx");
- })
- .catch(() => {
- proxy.$modal.msg("宸插彇娑�");
- });
-};
-onMounted(() => {
- getList();
-});
-</script>
-
-<style scoped></style>
diff --git a/src/views/personnelManagement/payrollManagement/components/formDia.vue b/src/views/personnelManagement/payrollManagement/components/formDia.vue
index e4cf0b3..cf93559 100644
--- a/src/views/personnelManagement/payrollManagement/components/formDia.vue
+++ b/src/views/personnelManagement/payrollManagement/components/formDia.vue
@@ -168,8 +168,8 @@
<script setup>
import {ref} from "vue";
-import {getStaffJoinInfo, getStaffOnJob, staffJoinAdd, staffJoinUpdate} from "@/api/personnelManagement/onboarding.js";
import {compensationAdd, compensationUpdate} from "@/api/personnelManagement/payrollManagement.js";
+import {staffOnJobInfo, staffOnJobListPage} from "@/api/personnelManagement/staffOnJob.js";
const { proxy } = getCurrentInstance()
const emit = defineEmits(['close'])
@@ -234,12 +234,16 @@
const openDialog = (type, row) => {
operationType.value = type;
dialogFormVisible.value = true;
- getStaffOnJob().then(res => {
- personList.value = res.data
- })
+ staffOnJobListPage({
+ current: -1,
+ size: -1,
+ staffState: 1
+ }).then(res => {
+ personList.value = res.data.records || []
+ })
form.value = {}
if (operationType.value === 'edit') {
- getStaffJoinInfo(row.id).then(res => {
+ staffOnJobInfo(row.staffId).then(res => {
form.value = {...row}
form.value.payDate = form.value.payDate + '-01'
})
diff --git a/src/views/personnelManagement/payrollManagement/index.vue b/src/views/personnelManagement/payrollManagement/index.vue
index 24e3dd8..f17f42e 100644
--- a/src/views/personnelManagement/payrollManagement/index.vue
+++ b/src/views/personnelManagement/payrollManagement/index.vue
@@ -53,7 +53,6 @@
import { Search } from "@element-plus/icons-vue";
import {onMounted, ref, reactive, toRefs, getCurrentInstance, nextTick} from "vue";
import FormDia from "@/views/personnelManagement/payrollManagement/components/formDia.vue";
-import {staffJoinDel} from "@/api/personnelManagement/onboarding.js";
import {ElMessageBox} from "element-plus";
import dayjs from "dayjs";
import {compensationDelete, compensationListPage} from "@/api/personnelManagement/payrollManagement.js";
diff --git a/src/views/personnelManagement/scheduling/index.vue b/src/views/personnelManagement/scheduling/index.vue
index 251dbe9..19d2062 100644
--- a/src/views/personnelManagement/scheduling/index.vue
+++ b/src/views/personnelManagement/scheduling/index.vue
@@ -253,9 +253,9 @@
import {useDict} from "@/utils/dict.js"
import {Plus, Download, Search, Refresh} from '@element-plus/icons-vue'
import {save, del, delByIds, listPage} from "@/api/personnelManagement/scheduling.js"
-import {getStaffOnJob} from "@/api/personnelManagement/onboarding.js";
import dayjs from "dayjs";
import pagination from "@/components/PIMTable/Pagination.vue";
+import {staffOnJobListPage} from "@/api/personnelManagement/staffOnJob.js";
const { proxy } = getCurrentInstance();
@@ -317,8 +317,12 @@
* 鑾峰彇褰撳墠鍦ㄨ亴浜哄憳鍒楄〃
*/
const getPersonList = () => {
- getStaffOnJob().then(res => {
- personList.value = res.data
+ staffOnJobListPage({
+ current: -1,
+ size: -1,
+ staffState: 1
+ }).then(res => {
+ personList.value = res.data.records || []
})
};
const paginationChange = (obj) => {
diff --git a/src/views/personnelManagement/selfService/index.vue b/src/views/personnelManagement/selfService/index.vue
index ca683c0..647f149 100644
--- a/src/views/personnelManagement/selfService/index.vue
+++ b/src/views/personnelManagement/selfService/index.vue
@@ -221,8 +221,7 @@
const { proxy } = getCurrentInstance()
import { getUserProfile } from '@/api/system/user.js'
-import {staffJoinUpdate, staffJoinListPage} from "@/api/personnelManagement/onboarding.js";
-import { fa, id } from 'element-plus/es/locales.mjs'
+import {staffOnJobListPage, updateStaffOnJob} from "@/api/personnelManagement/staffOnJob.js";
const tableLoading = ref(false)
// 鍒嗛〉鍙傛暟
@@ -572,7 +571,7 @@
currentUser.value = res.data
// console.log("----",currentUser.value)
//寰楀埌浜哄憳鍒楄〃
- staffJoinListPage({staffState: 1}).then(res => {
+ staffOnJobListPage({staffState: 1}).then(res => {
//绛涢�夊嚭鍜宑urrentUser鍚屽悕鐨勪汉鍛�
// let tableData = res.data.records
user.value = res.data.records.find(item => item.staffName === currentUser.value.userName)
@@ -604,18 +603,15 @@
const userRes = await getUserProfile();
if (userRes.code === 200) {
currentUser.value = userRes.data;
- const staffListRes = await staffJoinListPage({ staffState: 1 });
+ const staffListRes = await staffOnJobListPage({ staffState: 1 });
user.value = staffListRes.data.records.find(item => item.staffName === currentUser.value.userName);
- // console.log("++++", user.value);
-
Object.assign(joinForm, user.value);
joinForm.staffName = profileForm.name;
joinForm.phone = profileForm.phone;
joinForm.email = profileForm.email;
joinForm.adress = profileForm.adress;
- console.log(joinForm)
// 璋冪敤鏇存柊涓汉淇℃伅鐨勬帴鍙�
- staffJoinUpdate(joinForm).then(res => {
+ updateStaffOnJob(user.value.id, joinForm).then(res => {
if (res.code === 200) {
ElMessage.success('涓汉淇℃伅淇濆瓨鎴愬姛');
getProfile();
--
Gitblit v1.9.3