index.vue 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848
  1. <template>
  2. <div class="app-container">
  3. <el-card>
  4. <!-- 顶部切换 -->
  5. <div class="tab-container">
  6. <el-radio-group v-model="currentTab" size="large">
  7. <el-radio-button value="non-cadre">非干部</el-radio-button>
  8. <el-radio-button value="cadre">干部</el-radio-button>
  9. </el-radio-group>
  10. </div>
  11. <!-- 查询条件 -->
  12. <div class="filter-container">
  13. <el-form :model="queryParams" ref="queryFormRef" :inline="true" class="search-form">
  14. <el-form-item label="姓名" prop="employeeName">
  15. <el-input v-model="queryParams.employeeName" placeholder="请输入姓名" clearable style="width: 200px" />
  16. </el-form-item>
  17. <el-form-item label="考核月份" prop="assessmentMonth">
  18. <el-date-picker v-model="queryParams.assessmentMonth" type="month" placeholder="请选择考核月份"
  19. value-format="YYYY-MM" style="width: 200px" />
  20. </el-form-item>
  21. <el-form-item>
  22. <el-button type="primary" icon="Search" @click="handleQuery">查询</el-button>
  23. <el-button icon="Refresh" @click="resetQuery">重置</el-button>
  24. </el-form-item>
  25. </el-form>
  26. </div>
  27. <!-- 操作按钮 -->
  28. <div class="operation-container">
  29. <!-- 非干部操作按钮 -->
  30. <div v-if="currentTab === 'non-cadre'" class="left-buttons">
  31. <el-button type="primary" plain icon="Plus" @click="handleAdd">新增</el-button>
  32. <el-button type="warning" plain icon="Download" @click="handleExport">导出</el-button>
  33. </div>
  34. <!-- 干部模式时显示空白占位 -->
  35. <div v-else class="left-buttons"></div>
  36. <div class="right-buttons">
  37. <el-button type="primary" @click="generateMonthlyAssessment">生成本月考核表</el-button>
  38. </div>
  39. </div>
  40. <!-- 非干部数据表格 -->
  41. <div v-if="currentTab === 'non-cadre'">
  42. <el-table v-loading="loading" :data="nonCadreList" border fit highlight-current-row style="width: 100%; margin-top: 20px;">
  43. <el-table-column label="大队" prop="brigade" align="center" min-width="100" />
  44. <el-table-column label="用工形式" prop="employmentType" align="center" min-width="100" />
  45. <el-table-column label="员工编号" prop="employeeCode" align="center" min-width="120" />
  46. <el-table-column label="员工姓名" prop="employeeName" align="center" min-width="120" />
  47. <el-table-column label="考核组" prop="assessmentGroup" align="center" min-width="100" />
  48. <el-table-column label="分管班组长" prop="teamLeader" align="center" min-width="120" />
  49. <el-table-column label="分管主管" prop="supervisor" align="center" min-width="120" />
  50. <el-table-column label="红线指标触发次数" prop="redLineTriggerCount" align="center" min-width="140" />
  51. <el-table-column label="红线指标依据" prop="redLineBasis" align="center" min-width="120" show-overflow-tooltip />
  52. <el-table-column label="核心指标分值" prop="coreIndicatorScore" align="center" min-width="120" />
  53. <el-table-column label="核心指标依据" prop="coreIndicatorBasis" align="center" min-width="120" show-overflow-tooltip />
  54. <el-table-column label="其他指标分值" prop="otherIndicatorScore" align="center" min-width="120" />
  55. <el-table-column label="其他指标依据" prop="otherIndicatorBasis" align="center" min-width="120" show-overflow-tooltip />
  56. <el-table-column label="其他指标中的安全(仅含SOC/站品控检查扣分)分值" prop="safetyWithSocScore" align="center" min-width="200" show-overflow-tooltip />
  57. <el-table-column label="其他指标中的安全(仅含SOC/站品控检查扣分)依据" prop="safetyWithSocBasis" align="center" min-width="200" show-overflow-tooltip />
  58. <el-table-column label="其他指标中的安全(不含SOC/站品控检查扣分)分值" prop="safetyWithoutSocScore" align="center" min-width="200" show-overflow-tooltip />
  59. <el-table-column label="其他指标中的安全(不含SOC/站品控检查扣分)依据" prop="safetyWithoutSocBasis" align="center" min-width="200" show-overflow-tooltip />
  60. <el-table-column label="其他指标中的非安全指标扣分" prop="nonSafetyDeduction" align="center" min-width="160" show-overflow-tooltip />
  61. <el-table-column label="其他指标中的非安全指标扣分依据" prop="nonSafetyDeductionBasis" align="center" min-width="160" show-overflow-tooltip />
  62. <el-table-column label="非核心安全+核心扣分" prop="nonCoreSafetyCoreDeduction" align="center" min-width="140" />
  63. <el-table-column label="SOC/站品控检查的涉及核心、安全指标扣分" prop="socSafetyCoreDeduction" align="center" min-width="200" show-overflow-tooltip />
  64. <el-table-column label="SOC/站品控检查的涉及核心、安全指标扣分依据" prop="socSafetyCoreDeductionBasis" align="center" min-width="200" show-overflow-tooltip />
  65. <el-table-column label="分管员工数量" prop="managedEmployeeCount" align="center" min-width="120" />
  66. <el-table-column label="扣分平均值" prop="averageDeduction" align="center" min-width="100" />
  67. <el-table-column label="总分" prop="totalScore" align="center" min-width="100" sortable />
  68. <el-table-column label="奖励明细" prop="rewardDetails" align="center" min-width="120" show-overflow-tooltip />
  69. <el-table-column label="惩罚明细" prop="penaltyDetails" align="center" min-width="120" show-overflow-tooltip />
  70. <el-table-column label="奖励(元)" prop="rewardAmount" align="center" min-width="100" />
  71. <el-table-column label="扣罚(元)" prop="penaltyAmount" align="center" min-width="100" />
  72. <el-table-column label="考核结果" prop="assessmentResult" align="center" min-width="100" />
  73. <el-table-column label="考核结果备注" prop="assessmentResultRemark" align="center" min-width="140" show-overflow-tooltip />
  74. <el-table-column label="应用方式" prop="applicationMethod" align="center" min-width="100" />
  75. <el-table-column label="应用方式备注" prop="applicationMethodRemark" align="center" min-width="140" show-overflow-tooltip />
  76. <el-table-column label="是否豁免" prop="isExempted" align="center" min-width="100">
  77. <template #default="scope">
  78. <el-tag :type="scope.row.isExempted ? 'success' : 'info'">
  79. {{ scope.row.isExempted ? '是' : '否' }}
  80. </el-tag>
  81. </template>
  82. </el-table-column>
  83. <el-table-column label="是否豁免备注" prop="exemptionRemark" align="center" min-width="140" show-overflow-tooltip />
  84. <el-table-column label="考核月份" prop="assessmentMonth" align="center" min-width="120" />
  85. <el-table-column label="操作" align="center" width="150" fixed="right">
  86. <template #default="scope">
  87. <el-button size="small" type="primary" link @click="handleEdit(scope.row, 'non-cadre')">修改</el-button>
  88. <el-button size="small" type="danger" link @click="handleDelete(scope.row)">删除</el-button>
  89. </template>
  90. </el-table-column>
  91. </el-table>
  92. </div>
  93. <!-- 干部数据表格 -->
  94. <div v-else>
  95. <el-table v-loading="loading" :data="cadreList" border fit highlight-current-row style="width: 100%; margin-top: 20px;">
  96. <el-table-column label="员工姓名" prop="employeeName" align="center" min-width="120" />
  97. <el-table-column label="岗位" prop="position" align="center" min-width="120" />
  98. <el-table-column label="区域" prop="area" align="center" min-width="100" />
  99. <el-table-column label="红线扣分" prop="redLineDeduction" align="center" min-width="100" />
  100. <el-table-column label="红线扣分豁免情况" prop="redLineExemption" align="center" min-width="140" show-overflow-tooltip />
  101. <el-table-column label="违规排名扣分" prop="violationRankingDeduction" align="center" min-width="140" />
  102. <el-table-column label="违规排名扣分豁免情况" prop="violationRankingExemption" align="center" min-width="180" show-overflow-tooltip />
  103. <el-table-column label="技能排名扣分" prop="skillRankingDeduction" align="center" min-width="140" />
  104. <el-table-column label="技能排名扣分豁免情况" prop="skillRankingExemption" align="center" min-width="180" show-overflow-tooltip />
  105. <el-table-column label="总分" prop="totalScore" align="center" min-width="100" sortable />
  106. <el-table-column label="考核结果" prop="assessmentResult" align="center" min-width="120" />
  107. <el-table-column label="考核结果备注" prop="assessmentResultRemark" align="center" min-width="140" show-overflow-tooltip />
  108. <el-table-column label="考核月份" prop="assessmentMonth" align="center" min-width="120" />
  109. <el-table-column label="应用方式" prop="applicationMethod" align="center" min-width="120" />
  110. <el-table-column label="应用方式备注" prop="applicationMethodRemark" align="center" min-width="160" show-overflow-tooltip />
  111. <el-table-column label="操作" align="center" width="150" fixed="right">
  112. <template #default="scope">
  113. <el-button size="small" type="primary" link @click="handleEdit(scope.row, 'cadre')">修改</el-button>
  114. <el-button size="small" type="danger" link @click="handleDelete(scope.row)">删除</el-button>
  115. </template>
  116. </el-table-column>
  117. </el-table>
  118. </div>
  119. <!-- 分页 -->
  120. <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum"
  121. v-model:limit="queryParams.pageSize" @pagination="getList" />
  122. </el-card>
  123. <!-- 编辑/新增弹窗 -->
  124. <el-dialog :title="dialog.title" v-model="dialog.visible" width="80%" :close-on-click-modal="false">
  125. <!-- 非干部表单 -->
  126. <el-form v-if="dialog.type === 'non-cadre'" :model="nonCadreForm" ref="formRef" :rules="nonCadreRules" label-width="180px" class="form-container">
  127. <el-row :gutter="20">
  128. <el-col :span="8">
  129. <el-form-item label="大队" prop="brigade">
  130. <el-input v-model="nonCadreForm.brigade" placeholder="请输入大队" />
  131. </el-form-item>
  132. </el-col>
  133. <el-col :span="8">
  134. <el-form-item label="用工形式" prop="employmentType">
  135. <el-select v-model="nonCadreForm.employmentType" placeholder="请选择用工形式" style="width: 100%">
  136. <el-option v-for="item in employmentTypeOptions" :key="item.value" :label="item.label" :value="item.value" />
  137. </el-select>
  138. </el-form-item>
  139. </el-col>
  140. <el-col :span="8">
  141. <el-form-item label="员工编号" prop="employeeCode">
  142. <el-input v-model="nonCadreForm.employeeCode" placeholder="请输入员工编号" />
  143. </el-form-item>
  144. </el-col>
  145. </el-row>
  146. <el-row :gutter="20">
  147. <el-col :span="8">
  148. <el-form-item label="员工姓名" prop="employeeName">
  149. <el-input v-model="nonCadreForm.employeeName" placeholder="请输入员工姓名" />
  150. </el-form-item>
  151. </el-col>
  152. <el-col :span="8">
  153. <el-form-item label="考核组" prop="assessmentGroup">
  154. <el-input v-model="nonCadreForm.assessmentGroup" placeholder="请输入考核组" />
  155. </el-form-item>
  156. </el-col>
  157. <el-col :span="8">
  158. <el-form-item label="考核月份" prop="assessmentMonth">
  159. <el-date-picker v-model="nonCadreForm.assessmentMonth" type="month" placeholder="请选择考核月份"
  160. value-format="YYYY-MM" style="width: 100%" />
  161. </el-form-item>
  162. </el-col>
  163. </el-row>
  164. <el-row :gutter="20">
  165. <el-col :span="8">
  166. <el-form-item label="分管班组长" prop="teamLeader">
  167. <el-input v-model="nonCadreForm.teamLeader" placeholder="请输入分管班组长" />
  168. </el-form-item>
  169. </el-col>
  170. <el-col :span="8">
  171. <el-form-item label="分管主管" prop="supervisor">
  172. <el-input v-model="nonCadreForm.supervisor" placeholder="请输入分管主管" />
  173. </el-form-item>
  174. </el-col>
  175. <el-col :span="8">
  176. <el-form-item label="分管员工数量" prop="managedEmployeeCount">
  177. <el-input-number v-model="nonCadreForm.managedEmployeeCount" :min="0" style="width: 100%" />
  178. </el-form-item>
  179. </el-col>
  180. </el-row>
  181. <el-divider content-position="left">红线指标</el-divider>
  182. <el-row :gutter="20">
  183. <el-col :span="12">
  184. <el-form-item label="红线指标触发次数" prop="redLineTriggerCount">
  185. <el-input-number v-model="nonCadreForm.redLineTriggerCount" :min="0" style="width: 100%" />
  186. </el-form-item>
  187. </el-col>
  188. <el-col :span="12">
  189. <el-form-item label="红线指标依据" prop="redLineBasis">
  190. <el-input v-model="nonCadreForm.redLineBasis" type="textarea" :rows="2" placeholder="请输入红线指标依据" />
  191. </el-form-item>
  192. </el-col>
  193. </el-row>
  194. <el-divider content-position="left">核心指标</el-divider>
  195. <el-row :gutter="20">
  196. <el-col :span="12">
  197. <el-form-item label="核心指标分值" prop="coreIndicatorScore">
  198. <el-input-number v-model="nonCadreForm.coreIndicatorScore" :min="0" :precision="2" style="width: 100%" />
  199. </el-form-item>
  200. </el-col>
  201. <el-col :span="12">
  202. <el-form-item label="核心指标依据" prop="coreIndicatorBasis">
  203. <el-input v-model="nonCadreForm.coreIndicatorBasis" type="textarea" :rows="2" placeholder="请输入核心指标依据" />
  204. </el-form-item>
  205. </el-col>
  206. </el-row>
  207. <el-divider content-position="left">其他指标</el-divider>
  208. <el-row :gutter="20">
  209. <el-col :span="12">
  210. <el-form-item label="其他指标分值" prop="otherIndicatorScore">
  211. <el-input-number v-model="nonCadreForm.otherIndicatorScore" :min="0" :precision="2" style="width: 100%" />
  212. </el-form-item>
  213. </el-col>
  214. <el-col :span="12">
  215. <el-form-item label="其他指标依据" prop="otherIndicatorBasis">
  216. <el-input v-model="nonCadreForm.otherIndicatorBasis" type="textarea" :rows="2" placeholder="请输入其他指标依据" />
  217. </el-form-item>
  218. </el-col>
  219. </el-row>
  220. <el-divider content-position="left">其他指标中的安全(仅含SOC/站品控检查扣分)</el-divider>
  221. <el-row :gutter="20">
  222. <el-col :span="12">
  223. <el-form-item label="分值" prop="safetyWithSocScore">
  224. <el-input-number v-model="nonCadreForm.safetyWithSocScore" :min="0" :precision="2" style="width: 100%" />
  225. </el-form-item>
  226. </el-col>
  227. <el-col :span="12">
  228. <el-form-item label="依据" prop="safetyWithSocBasis">
  229. <el-input v-model="nonCadreForm.safetyWithSocBasis" type="textarea" :rows="2" placeholder="请输入依据" />
  230. </el-form-item>
  231. </el-col>
  232. </el-row>
  233. <el-divider content-position="left">其他指标中的安全(不含SOC/站品控检查扣分)</el-divider>
  234. <el-row :gutter="20">
  235. <el-col :span="12">
  236. <el-form-item label="分值" prop="safetyWithoutSocScore">
  237. <el-input-number v-model="nonCadreForm.safetyWithoutSocScore" :min="0" :precision="2" style="width: 100%" />
  238. </el-form-item>
  239. </el-col>
  240. <el-col :span="12">
  241. <el-form-item label="依据" prop="safetyWithoutSocBasis">
  242. <el-input v-model="nonCadreForm.safetyWithoutSocBasis" type="textarea" :rows="2" placeholder="请输入依据" />
  243. </el-form-item>
  244. </el-col>
  245. </el-row>
  246. <el-divider content-position="left">其他指标中的非安全指标扣分</el-divider>
  247. <el-row :gutter="20">
  248. <el-col :span="12">
  249. <el-form-item label="扣分" prop="nonSafetyDeduction">
  250. <el-input-number v-model="nonCadreForm.nonSafetyDeduction" :min="0" :precision="2" style="width: 100%" />
  251. </el-form-item>
  252. </el-col>
  253. <el-col :span="12">
  254. <el-form-item label="依据" prop="nonSafetyDeductionBasis">
  255. <el-input v-model="nonCadreForm.nonSafetyDeductionBasis" type="textarea" :rows="2" placeholder="请输入依据" />
  256. </el-form-item>
  257. </el-col>
  258. </el-row>
  259. <el-divider content-position="left">综合扣分</el-divider>
  260. <el-row :gutter="20">
  261. <el-col :span="12">
  262. <el-form-item label="非核心安全+核心扣分" prop="nonCoreSafetyCoreDeduction">
  263. <el-input-number v-model="nonCadreForm.nonCoreSafetyCoreDeduction" :min="0" :precision="2" style="width: 100%" />
  264. </el-form-item>
  265. </el-col>
  266. <el-col :span="12">
  267. <el-form-item label="SOC/站品控检查的涉及核心、安全指标扣分" prop="socSafetyCoreDeduction">
  268. <el-input-number v-model="nonCadreForm.socSafetyCoreDeduction" :min="0" :precision="2" style="width: 100%" />
  269. </el-form-item>
  270. </el-col>
  271. </el-row>
  272. <el-row :gutter="20">
  273. <el-col :span="24">
  274. <el-form-item label="SOC/站品控检查的涉及核心、安全指标扣分依据" prop="socSafetyCoreDeductionBasis">
  275. <el-input v-model="nonCadreForm.socSafetyCoreDeductionBasis" type="textarea" :rows="2" placeholder="请输入依据" />
  276. </el-form-item>
  277. </el-col>
  278. </el-row>
  279. <el-divider content-position="left">统计信息</el-divider>
  280. <el-row :gutter="20">
  281. <el-col :span="8">
  282. <el-form-item label="扣分平均值" prop="averageDeduction">
  283. <el-input-number v-model="nonCadreForm.averageDeduction" :min="0" :precision="2" style="width: 100%" />
  284. </el-form-item>
  285. </el-col>
  286. <el-col :span="8">
  287. <el-form-item label="总分" prop="totalScore">
  288. <el-input-number v-model="nonCadreForm.totalScore" :min="0" :precision="2" style="width: 100%" />
  289. </el-form-item>
  290. </el-col>
  291. <el-col :span="8">
  292. <el-form-item label="奖励(元)" prop="rewardAmount">
  293. <el-input-number v-model="nonCadreForm.rewardAmount" :min="0" :precision="2" style="width: 100%" />
  294. </el-form-item>
  295. </el-col>
  296. </el-row>
  297. <el-row :gutter="20">
  298. <el-col :span="8">
  299. <el-form-item label="扣罚(元)" prop="penaltyAmount">
  300. <el-input-number v-model="nonCadreForm.penaltyAmount" :min="0" :precision="2" style="width: 100%" />
  301. </el-form-item>
  302. </el-col>
  303. <el-col :span="8">
  304. <el-form-item label="考核结果" prop="assessmentResult">
  305. <el-select v-model="nonCadreForm.assessmentResult" placeholder="请选择考核结果" style="width: 100%">
  306. <el-option v-for="item in assessmentResultOptions" :key="item.value" :label="item.label" :value="item.value" />
  307. </el-select>
  308. </el-form-item>
  309. </el-col>
  310. <el-col :span="8">
  311. <el-form-item label="应用方式" prop="applicationMethod">
  312. <el-select v-model="nonCadreForm.applicationMethod" placeholder="请选择应用方式" style="width: 100%">
  313. <el-option v-for="item in applicationMethodOptions" :key="item.value" :label="item.label" :value="item.value" />
  314. </el-select>
  315. </el-form-item>
  316. </el-col>
  317. </el-row>
  318. <el-row :gutter="20">
  319. <el-col :span="12">
  320. <el-form-item label="奖励明细" prop="rewardDetails">
  321. <el-input v-model="nonCadreForm.rewardDetails" type="textarea" :rows="2" placeholder="请输入奖励明细" />
  322. </el-form-item>
  323. </el-col>
  324. <el-col :span="12">
  325. <el-form-item label="惩罚明细" prop="penaltyDetails">
  326. <el-input v-model="nonCadreForm.penaltyDetails" type="textarea" :rows="2" placeholder="请输入惩罚明细" />
  327. </el-form-item>
  328. </el-col>
  329. </el-row>
  330. <el-row :gutter="20">
  331. <el-col :span="12">
  332. <el-form-item label="考核结果备注" prop="assessmentResultRemark">
  333. <el-input v-model="nonCadreForm.assessmentResultRemark" type="textarea" :rows="2" placeholder="请输入考核结果备注" />
  334. </el-form-item>
  335. </el-col>
  336. <el-col :span="12">
  337. <el-form-item label="应用方式备注" prop="applicationMethodRemark">
  338. <el-input v-model="nonCadreForm.applicationMethodRemark" type="textarea" :rows="2" placeholder="请输入应用方式备注" />
  339. </el-form-item>
  340. </el-col>
  341. </el-row>
  342. <el-divider content-position="left">豁免信息</el-divider>
  343. <el-row :gutter="20">
  344. <el-col :span="12">
  345. <el-form-item label="是否豁免" prop="isExempted">
  346. <el-switch v-model="nonCadreForm.isExempted" active-text="是" inactive-text="否" />
  347. </el-form-item>
  348. </el-col>
  349. <el-col :span="12">
  350. <el-form-item label="是否豁免备注" prop="exemptionRemark">
  351. <el-input v-model="nonCadreForm.exemptionRemark" type="textarea" :rows="2" placeholder="请输入豁免备注" />
  352. </el-form-item>
  353. </el-col>
  354. </el-row>
  355. </el-form>
  356. <!-- 干部表单 -->
  357. <el-form v-else :model="cadreForm" ref="formRef" :rules="cadreRules" label-width="180px" class="form-container">
  358. <el-row :gutter="20">
  359. <el-col :span="8">
  360. <el-form-item label="员工姓名" prop="employeeName">
  361. <el-input v-model="cadreForm.employeeName" placeholder="请输入员工姓名" />
  362. </el-form-item>
  363. </el-col>
  364. <el-col :span="8">
  365. <el-form-item label="岗位" prop="position">
  366. <el-input v-model="cadreForm.position" placeholder="请输入岗位" />
  367. </el-form-item>
  368. </el-col>
  369. <el-col :span="8">
  370. <el-form-item label="区域" prop="area">
  371. <el-input v-model="cadreForm.area" placeholder="请输入区域" />
  372. </el-form-item>
  373. </el-col>
  374. </el-row>
  375. <el-row :gutter="20">
  376. <el-col :span="8">
  377. <el-form-item label="考核月份" prop="assessmentMonth">
  378. <el-date-picker v-model="cadreForm.assessmentMonth" type="month" placeholder="请选择考核月份"
  379. value-format="YYYY-MM" style="width: 100%" />
  380. </el-form-item>
  381. </el-col>
  382. <el-col :span="8">
  383. <el-form-item label="考核结果" prop="assessmentResult">
  384. <el-select v-model="cadreForm.assessmentResult" placeholder="请选择考核结果" style="width: 100%">
  385. <el-option v-for="item in assessmentResultOptions" :key="item.value" :label="item.label" :value="item.value" />
  386. </el-select>
  387. </el-form-item>
  388. </el-col>
  389. <el-col :span="8">
  390. <el-form-item label="应用方式" prop="applicationMethod">
  391. <el-select v-model="cadreForm.applicationMethod" placeholder="请选择应用方式" style="width: 100%">
  392. <el-option v-for="item in applicationMethodOptions" :key="item.value" :label="item.label" :value="item.value" />
  393. </el-select>
  394. </el-form-item>
  395. </el-col>
  396. </el-row>
  397. <el-divider content-position="left">红线扣分</el-divider>
  398. <el-row :gutter="20">
  399. <el-col :span="12">
  400. <el-form-item label="红线扣分" prop="redLineDeduction">
  401. <el-input-number v-model="cadreForm.redLineDeduction" :min="0" :precision="2" style="width: 100%" />
  402. </el-form-item>
  403. </el-col>
  404. <el-col :span="12">
  405. <el-form-item label="红线扣分豁免情况" prop="redLineExemption">
  406. <el-input v-model="cadreForm.redLineExemption" type="textarea" :rows="2" placeholder="请输入豁免情况" />
  407. </el-form-item>
  408. </el-col>
  409. </el-row>
  410. <el-divider content-position="left">违规排名扣分</el-divider>
  411. <el-row :gutter="20">
  412. <el-col :span="12">
  413. <el-form-item label="违规排名扣分" prop="violationRankingDeduction">
  414. <el-input-number v-model="cadreForm.violationRankingDeduction" :min="0" :precision="2" style="width: 100%" />
  415. </el-form-item>
  416. </el-col>
  417. <el-col :span="12">
  418. <el-form-item label="违规排名扣分豁免情况" prop="violationRankingExemption">
  419. <el-input v-model="cadreForm.violationRankingExemption" type="textarea" :rows="2" placeholder="请输入豁免情况" />
  420. </el-form-item>
  421. </el-col>
  422. </el-row>
  423. <el-divider content-position="left">技能排名扣分</el-divider>
  424. <el-row :gutter="20">
  425. <el-col :span="12">
  426. <el-form-item label="技能排名扣分" prop="skillRankingDeduction">
  427. <el-input-number v-model="cadreForm.skillRankingDeduction" :min="0" :precision="2" style="width: 100%" />
  428. </el-form-item>
  429. </el-col>
  430. <el-col :span="12">
  431. <el-form-item label="技能排名扣分豁免情况" prop="skillRankingExemption">
  432. <el-input v-model="cadreForm.skillRankingExemption" type="textarea" :rows="2" placeholder="请输入豁免情况" />
  433. </el-form-item>
  434. </el-col>
  435. </el-row>
  436. <el-divider content-position="left">统计信息</el-divider>
  437. <el-row :gutter="20">
  438. <el-col :span="12">
  439. <el-form-item label="总分" prop="totalScore">
  440. <el-input-number v-model="cadreForm.totalScore" :min="0" :precision="2" style="width: 100%" />
  441. </el-form-item>
  442. </el-col>
  443. </el-row>
  444. <el-row :gutter="20">
  445. <el-col :span="12">
  446. <el-form-item label="考核结果备注" prop="assessmentResultRemark">
  447. <el-input v-model="cadreForm.assessmentResultRemark" type="textarea" :rows="2" placeholder="请输入考核结果备注" />
  448. </el-form-item>
  449. </el-col>
  450. <el-col :span="12">
  451. <el-form-item label="应用方式备注" prop="applicationMethodRemark">
  452. <el-input v-model="cadreForm.applicationMethodRemark" type="textarea" :rows="2" placeholder="请输入应用方式备注" />
  453. </el-form-item>
  454. </el-col>
  455. </el-row>
  456. </el-form>
  457. <template #footer>
  458. <div class="dialog-footer">
  459. <el-button @click="dialog.visible = false">取消</el-button>
  460. <el-button type="primary" @click="submitForm">确定</el-button>
  461. </div>
  462. </template>
  463. </el-dialog>
  464. </div>
  465. </template>
  466. <script setup>
  467. import { ref, reactive, onMounted, getCurrentInstance } from 'vue'
  468. import { ElMessage, ElMessageBox } from 'element-plus'
  469. // API导入(需要根据实际API路径调整)
  470. import { getNonCadreMonthlyAssessList, addNonCadreMonthlyAssess, updateNonCadreMonthlyAssess, deleteNonCadreMonthlyAssess } from '@/api/performance/nonCadreMonthlyAssess.js'
  471. const { proxy } = getCurrentInstance()
  472. // 响应式数据
  473. const loading = ref(false)
  474. const total = ref(0)
  475. const queryFormRef = ref()
  476. const formRef = ref()
  477. const currentTab = ref('non-cadre')
  478. // 查询参数
  479. const queryParams = reactive({
  480. pageNum: 1,
  481. pageSize: 10,
  482. employeeName: '',
  483. assessmentMonth: ''
  484. })
  485. // 非干部表单数据
  486. const nonCadreForm = reactive({
  487. brigade: '',
  488. employmentType: '',
  489. employeeCode: '',
  490. employeeName: '',
  491. assessmentGroup: '',
  492. teamLeader: '',
  493. supervisor: '',
  494. managedEmployeeCount: 0,
  495. assessmentMonth: '',
  496. redLineTriggerCount: 0,
  497. redLineBasis: '',
  498. coreIndicatorScore: 0,
  499. coreIndicatorBasis: '',
  500. otherIndicatorScore: 0,
  501. otherIndicatorBasis: '',
  502. safetyWithSocScore: 0,
  503. safetyWithSocBasis: '',
  504. safetyWithoutSocScore: 0,
  505. safetyWithoutSocBasis: '',
  506. nonSafetyDeduction: 0,
  507. nonSafetyDeductionBasis: '',
  508. nonCoreSafetyCoreDeduction: 0,
  509. socSafetyCoreDeduction: 0,
  510. socSafetyCoreDeductionBasis: '',
  511. averageDeduction: 0,
  512. totalScore: 0,
  513. rewardAmount: 0,
  514. penaltyAmount: 0,
  515. assessmentResult: '',
  516. applicationMethod: '',
  517. rewardDetails: '',
  518. penaltyDetails: '',
  519. assessmentResultRemark: '',
  520. applicationMethodRemark: '',
  521. isExempted: false,
  522. exemptionRemark: ''
  523. })
  524. // 干部表单数据
  525. const cadreForm = reactive({
  526. employeeName: '',
  527. position: '',
  528. area: '',
  529. assessmentMonth: '',
  530. redLineDeduction: 0,
  531. redLineExemption: '',
  532. violationRankingDeduction: 0,
  533. violationRankingExemption: '',
  534. skillRankingDeduction: 0,
  535. skillRankingExemption: '',
  536. totalScore: 0,
  537. assessmentResult: '',
  538. applicationMethod: '',
  539. assessmentResultRemark: '',
  540. applicationMethodRemark: ''
  541. })
  542. // 弹窗配置
  543. const dialog = reactive({
  544. visible: false,
  545. title: '',
  546. type: 'non-cadre'
  547. })
  548. // 数据列表
  549. const nonCadreList = ref([])
  550. const cadreList = ref([])
  551. // 选项配置
  552. const employmentTypeOptions = [
  553. { label: '正式员工', value: 'formal' },
  554. { label: '合同工', value: 'contract' },
  555. { label: '临时工', value: 'temporary' },
  556. { label: '实习生', value: 'intern' }
  557. ]
  558. const assessmentResultOptions = [
  559. { label: '优秀', value: 'excellent' },
  560. { label: '良好', value: 'good' },
  561. { label: '合格', value: 'qualified' },
  562. { label: '不合格', value: 'unqualified' }
  563. ]
  564. const applicationMethodOptions = [
  565. { label: '直接应用', value: 'direct' },
  566. { label: '加权计算', value: 'weighted' },
  567. { label: '特殊处理', value: 'special' }
  568. ]
  569. // 非干部表单验证规则
  570. const nonCadreRules = {
  571. employeeName: [{ required: true, message: '员工姓名不能为空', trigger: 'blur' }],
  572. employmentType: [{ required: true, message: '用工形式不能为空', trigger: 'change' }],
  573. assessmentGroup: [{ required: true, message: '考核组不能为空', trigger: 'blur' }],
  574. assessmentMonth: [{ required: true, message: '考核月份不能为空', trigger: 'change' }]
  575. }
  576. // 干部表单验证规则
  577. const cadreRules = {
  578. employeeName: [{ required: true, message: '员工姓名不能为空', trigger: 'blur' }],
  579. position: [{ required: true, message: '岗位不能为空', trigger: 'blur' }],
  580. assessmentMonth: [{ required: true, message: '考核月份不能为空', trigger: 'change' }],
  581. assessmentResult: [{ required: true, message: '考核结果不能为空', trigger: 'change' }]
  582. }
  583. // 获取数据列表
  584. const getList = async () => {
  585. loading.value = true
  586. try {
  587. if (currentTab.value === 'non-cadre') {
  588. const res = await getNonCadreMonthlyAssessList(queryParams)
  589. nonCadreList.value = res.rows || []
  590. total.value = res.total || 0
  591. } else {
  592. // 干部数据API(待实现)
  593. cadreList.value = []
  594. total.value = 0
  595. }
  596. } catch (error) {
  597. console.error('获取数据失败:', error)
  598. ElMessage.error('获取数据失败')
  599. } finally {
  600. loading.value = false
  601. }
  602. }
  603. // 查询
  604. const handleQuery = () => {
  605. queryParams.pageNum = 1
  606. getList()
  607. }
  608. // 重置查询
  609. const resetQuery = () => {
  610. queryFormRef.value?.resetFields()
  611. queryParams.pageNum = 1
  612. getList()
  613. }
  614. // 新增
  615. const handleAdd = () => {
  616. dialog.visible = true
  617. dialog.type = currentTab.value
  618. dialog.title = currentTab.value === 'non-cadre' ? '新增非干部月度考核' : '新增干部月度考核'
  619. // 重置表单数据
  620. if (currentTab.value === 'non-cadre') {
  621. Object.keys(nonCadreForm).forEach(key => {
  622. if (typeof nonCadreForm[key] === 'number') {
  623. nonCadreForm[key] = 0
  624. } else if (typeof nonCadreForm[key] === 'boolean') {
  625. nonCadreForm[key] = false
  626. } else {
  627. nonCadreForm[key] = ''
  628. }
  629. })
  630. } else {
  631. Object.keys(cadreForm).forEach(key => {
  632. if (typeof cadreForm[key] === 'number') {
  633. cadreForm[key] = 0
  634. } else if (typeof cadreForm[key] === 'boolean') {
  635. cadreForm[key] = false
  636. } else {
  637. cadreForm[key] = ''
  638. }
  639. })
  640. }
  641. }
  642. // 编辑
  643. const handleEdit = (row, type) => {
  644. dialog.visible = true
  645. dialog.type = type
  646. dialog.title = type === 'non-cadre' ? '编辑非干部月度考核' : '编辑干部月度考核'
  647. // 填充表单数据
  648. if (type === 'non-cadre') {
  649. Object.keys(nonCadreForm).forEach(key => {
  650. if (row[key] !== undefined) {
  651. nonCadreForm[key] = row[key]
  652. }
  653. })
  654. } else {
  655. Object.keys(cadreForm).forEach(key => {
  656. if (row[key] !== undefined) {
  657. cadreForm[key] = row[key]
  658. }
  659. })
  660. }
  661. }
  662. // 删除
  663. const handleDelete = async (row) => {
  664. try {
  665. await ElMessageBox.confirm('确认删除该考核记录吗?', '提示', {
  666. confirmButtonText: '确定',
  667. cancelButtonText: '取消',
  668. type: 'warning'
  669. })
  670. await deleteNonCadreMonthlyAssess(row.id)
  671. ElMessage.success('删除成功')
  672. getList()
  673. } catch (error) {
  674. if (error !== 'cancel') {
  675. ElMessage.error('删除失败')
  676. }
  677. }
  678. }
  679. // 提交表单
  680. const submitForm = async () => {
  681. const valid = await formRef.value?.validate()
  682. if (!valid) return
  683. try {
  684. if (dialog.type === 'non-cadre') {
  685. if (dialog.title === '新增非干部月度考核') {
  686. await addNonCadreMonthlyAssess(nonCadreForm)
  687. ElMessage.success('新增成功')
  688. } else {
  689. await updateNonCadreMonthlyAssess(nonCadreForm)
  690. ElMessage.success('更新成功')
  691. }
  692. } else {
  693. // 干部数据API(待实现)
  694. ElMessage.success('操作成功')
  695. }
  696. dialog.visible = false
  697. getList()
  698. } catch (error) {
  699. ElMessage.error('操作失败')
  700. }
  701. }
  702. // 导出
  703. const handleExport = async () => {
  704. try {
  705. ElMessage.success('导出功能开发中')
  706. } catch (error) {
  707. ElMessage.error('导出失败')
  708. }
  709. }
  710. // 生成本月考核表
  711. const generateMonthlyAssessment = async () => {
  712. try {
  713. ElMessage.success('生成本月考核表功能开发中')
  714. } catch (error) {
  715. ElMessage.error('生成失败')
  716. }
  717. }
  718. // 监听Tab切换
  719. const handleTabChange = () => {
  720. queryParams.pageNum = 1
  721. getList()
  722. }
  723. onMounted(() => {
  724. getList()
  725. })
  726. </script>
  727. <style lang="less" scoped>
  728. .app-container {
  729. padding: 20px;
  730. }
  731. .tab-container {
  732. margin-bottom: 20px;
  733. text-align: left;
  734. }
  735. .filter-container {
  736. // margin-bottom: 20px;
  737. }
  738. .search-form {
  739. display: flex;
  740. flex-wrap: wrap;
  741. gap: 10px;
  742. }
  743. .operation-container {
  744. margin-bottom: 20px;
  745. display: flex;
  746. justify-content: space-between;
  747. align-items: center;
  748. }
  749. .left-buttons {
  750. display: flex;
  751. gap: 10px;
  752. }
  753. .right-buttons {
  754. display: flex;
  755. gap: 10px;
  756. }
  757. .form-container {
  758. max-height: 70vh;
  759. overflow-y: auto;
  760. padding-right: 10px;
  761. }
  762. .el-divider {
  763. margin: 20px 0;
  764. }
  765. :deep(.el-form-item__label) {
  766. font-weight: 500;
  767. }
  768. </style>