classFeesIsOk.vue 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703
  1. <!-- -->
  2. <template>
  3. <div class="m-container">
  4. <h2>
  5. <div class="squrt"></div>
  6. 课酬列表
  7. </h2>
  8. <div class="m-core">
  9. <auth
  10. auths="courseScheduleTeacherSalary/openSalaryConfirm"
  11. v-if="isOpen == 0"
  12. >
  13. <div @click="openSalary" class="newBand">开启课酬确认</div>
  14. </auth>
  15. <auth
  16. v-if="isOpen == 1"
  17. auths="courseScheduleTeacherSalary/closeSalaryConfirm"
  18. >
  19. <div @click="closeSalary" class="newBand">关闭课酬确认</div>
  20. </auth>
  21. <save-form
  22. :inline="true"
  23. @submit="search"
  24. @reset="onReSet"
  25. :model="searchForm"
  26. >
  27. <el-form-item>
  28. <el-input
  29. v-model.trim="searchForm.search"
  30. @keyup.enter.native="search"
  31. clearable
  32. placeholder="课程编号、课程组名称"
  33. ></el-input>
  34. </el-form-item>
  35. <el-form-item prop="organId">
  36. <el-select
  37. class="multiple"
  38. v-model.trim="searchForm.organIdList"
  39. filterable
  40. clearable
  41. placeholder="请选择分部"
  42. >
  43. <el-option
  44. v-for="(item, index) in selects.branchs"
  45. :key="index"
  46. :label="item.name"
  47. :value="item.id"
  48. ></el-option>
  49. </el-select>
  50. </el-form-item>
  51. <el-form-item prop="organId">
  52. <el-select
  53. class="multiple"
  54. v-model.trim="searchForm.groupType"
  55. filterable
  56. clearable
  57. placeholder="请选择课程组类型"
  58. >
  59. <el-option
  60. v-for="(item, index) in groupTypeList"
  61. :key="index"
  62. :label="item.label"
  63. :value="item.value"
  64. ></el-option>
  65. </el-select>
  66. </el-form-item>
  67. <el-form-item prop="belongDaya">
  68. <el-select
  69. v-model.trim="searchForm.belongDaya"
  70. clearable
  71. placeholder="请选择课酬类型"
  72. >
  73. <el-option
  74. v-for="(item, index) in belongDayaOption"
  75. :key="index"
  76. :label="item.label"
  77. :value="item.value"
  78. ></el-option>
  79. </el-select>
  80. </el-form-item>
  81. <el-form-item>
  82. <remoteSearch
  83. :commit="'setTeachers'"
  84. v-model="searchForm.teacherId"
  85. />
  86. <!-- <el-select
  87. placeholder="老师姓名"
  88. v-model="searchForm.teacherId"
  89. clearable
  90. filterable
  91. >
  92. <el-option
  93. v-for="(item, index) in selects.teachers"
  94. :label="item.realName"
  95. :value="item.id"
  96. :key="index"
  97. ></el-option>
  98. </el-select> -->
  99. </el-form-item>
  100. <el-form-item>
  101. <el-select
  102. placeholder="正常签到"
  103. v-model="searchForm.signInStatus"
  104. clearable
  105. >
  106. <el-option label="是" value="1"></el-option>
  107. <el-option label="否" value="0"></el-option>
  108. </el-select>
  109. </el-form-item>
  110. <el-form-item>
  111. <el-select
  112. placeholder="正常签退"
  113. v-model="searchForm.signOutStatus"
  114. clearable
  115. >
  116. <el-option label="是" value="1"></el-option>
  117. <el-option label="否" value="0"></el-option>
  118. </el-select>
  119. </el-form-item>
  120. <el-form-item>
  121. <el-select
  122. placeholder="状态"
  123. v-model="searchForm.confirmStatus"
  124. clearable
  125. >
  126. <el-option label="待确定" value="1"></el-option>
  127. <el-option label="已确定" value="2"></el-option>
  128. <el-option label="已完成" value="3"></el-option>
  129. </el-select>
  130. </el-form-item>
  131. <el-form-item>
  132. <el-date-picker
  133. :clearable="false"
  134. v-model="searchForm.month"
  135. style="width: 100%"
  136. type="month"
  137. value-format="yyyy-MM"
  138. placeholder="选择年月"
  139. ></el-date-picker>
  140. </el-form-item>
  141. <el-form-item>
  142. <el-button type="danger" native-type="submit">搜索</el-button>
  143. <el-button native-type="reset" type="primary">重置</el-button>
  144. <!-- export/isSettlementCourseSalarys -->
  145. <el-button
  146. @click="onExport"
  147. type="primary"
  148. v-permission="'export/isSettlementCourseSalarys'"
  149. style="background: #14928a; border: 1px solid #14928a"
  150. >导出</el-button
  151. >
  152. </el-form-item>
  153. </save-form>
  154. <div class="tableWrap">
  155. <el-table
  156. style="width: 100%"
  157. :header-cell-style="{ background: '#EDEEF0', color: '#444' }"
  158. :data="tableList"
  159. >
  160. <el-table-column
  161. align="center"
  162. prop="organName"
  163. label="分部"
  164. ></el-table-column>
  165. <el-table-column
  166. align="center"
  167. prop="groupType"
  168. width="100"
  169. label="课程组类型"
  170. >
  171. <template slot-scope="scope">{{
  172. scope.row.groupType | coursesType
  173. }}</template>
  174. </el-table-column>
  175. <el-table-column
  176. align="center"
  177. prop="courseScheduleId"
  178. label="课程编号"
  179. ></el-table-column>
  180. <el-table-column
  181. align="center"
  182. prop="courseScheduleId"
  183. width="150"
  184. label="时间"
  185. >
  186. <template slot-scope="scope">{{
  187. scope.row.startClassTime | dateForMinFormat
  188. }}</template>
  189. </el-table-column>
  190. <el-table-column
  191. align="center"
  192. prop="courseName"
  193. width="120"
  194. label="课程名称"
  195. ></el-table-column>
  196. <el-table-column
  197. align="center"
  198. prop="teacherId"
  199. label="老师编号"
  200. ></el-table-column>
  201. <el-table-column
  202. align="center"
  203. prop="teacherName"
  204. label="老师姓名"
  205. ></el-table-column>
  206. <el-table-column
  207. align="center"
  208. prop="courseScheduleId"
  209. width="150"
  210. label="签到时间"
  211. >
  212. <template slot-scope="scope">
  213. <p :class="scope.row.signInStatus == 1 ? '' : 'red'">
  214. {{ scope.row.signInTime | dateForMinFormat }}
  215. </p>
  216. <p :class="scope.row.signInStatus == 1 ? '' : 'red'">
  217. {{ scope.row.signInStatus | attendanceType }}
  218. </p>
  219. <p
  220. class="red"
  221. v-if="!scope.row.signInStatus && scope.row.signInStatus != 0"
  222. >
  223. 未签到
  224. </p>
  225. </template>
  226. </el-table-column>
  227. <el-table-column
  228. align="center"
  229. prop="courseScheduleId"
  230. width="150"
  231. label="签退时间"
  232. >
  233. <template slot-scope="scope">
  234. <p :class="scope.row.signOutStatus == 1 ? '' : 'red'">
  235. {{ scope.row.signOutTime | dateForMinFormat }}
  236. </p>
  237. <p :class="scope.row.signOutStatus == 1 ? '' : 'red'">
  238. {{ scope.row.signOutStatus | attendanceOutType }}
  239. </p>
  240. <p
  241. class="red"
  242. v-if="!scope.row.signOutStatus && scope.row.signOutStatus != 0"
  243. >
  244. 未签退
  245. </p>
  246. </template>
  247. </el-table-column>
  248. <!-- <el-table-column align="center" prop="actualReceipts" label="实际收款">
  249. <template slot-scope="scope">{{(scope.row.actualReceipts ? scope.row.actualReceipts : 0) + '元'}}</template>
  250. </el-table-column> -->
  251. <!-- expectSalary -->
  252. <el-table-column align="center" prop="belongDaya" label="课酬类型">
  253. <template slot-scope="scope">{{
  254. belongDaya[scope.row.belongDaya]
  255. }}</template>
  256. </el-table-column>
  257. <el-table-column align="center" prop="actualSalary" label="应发课酬">
  258. <template slot-scope="scope"
  259. >{{ scope.row.actualSalary | moneyFormat }}元</template
  260. >
  261. </el-table-column>
  262. <el-table-column align="center" prop="reduceSalary" label="课酬扣款">
  263. <template slot-scope="scope"
  264. >{{ scope.row.reduceSalary | moneyFormat }}元</template
  265. >
  266. </el-table-column>
  267. <el-table-column align="center" prop="finalSalary" label="结算课酬">
  268. <template slot-scope="scope"
  269. >{{ scope.row.finalSalary | moneyFormat }}元</template
  270. >
  271. </el-table-column>
  272. <el-table-column align="center" prop label="状态" >
  273. <template slot-scope="scope">{{
  274. scope.row.confirmStatus | confirmFilter
  275. }}</template>
  276. </el-table-column>
  277. <el-table-column
  278. align="center"
  279. prop="memo"
  280. label="备注"
  281. width="300"
  282. ></el-table-column>
  283. <el-table-column align="center" label="操作" fixed="right" v-if="$helpers.permission('teacherSalaryModifyLog/add')">
  284. <template slot-scope="scope">
  285. <auth auths='teacherSalaryModifyLog/add'>
  286. <el-button type="text" @click="resetSalary(scope.row)"
  287. >课酬调整</el-button
  288. >
  289. </auth>
  290. </template>
  291. </el-table-column>
  292. </el-table>
  293. <pagination
  294. sync
  295. :total.sync="rules.total"
  296. :page.sync="rules.page"
  297. :limit.sync="rules.limit"
  298. :page-sizes="rules.page_size"
  299. @pagination="getList"
  300. />
  301. </div>
  302. </div>
  303. <el-dialog title="课酬调整" :visible.sync="dialogVisible" width="400px">
  304. <div>
  305. <el-form
  306. ref="visibleForm"
  307. :model="visibleForm"
  308. class="visibleForm"
  309. :inline="true"
  310. label-width="60px"
  311. >
  312. <el-form-item
  313. label="应发"
  314. :rules="[
  315. { required: true, message: '请填写应发数', trigger: 'blur' },
  316. ]"
  317. prop="actualSalary"
  318. >
  319. <el-input-number
  320. :controls="false"
  321. :min="0"
  322. :precision="2"
  323. v-model.trim="visibleForm.actualSalary"
  324. type="number"
  325. @mousewheel.native.prevent
  326. ></el-input-number>
  327. </el-form-item>
  328. <el-form-item
  329. label="扣款"
  330. :rules="[
  331. { required: true, message: '请填写扣款数', trigger: 'blur' },
  332. ]"
  333. prop="reduceSalary"
  334. >
  335. <el-input-number
  336. :controls="false"
  337. :min="0"
  338. :precision="2"
  339. v-model.trim="visibleForm.reduceSalary"
  340. type="number"
  341. @mousewheel.native.prevent
  342. ></el-input-number>
  343. </el-form-item>
  344. <el-form-item label="实发">
  345. <el-input-number
  346. :controls="false"
  347. :min="0"
  348. :precision="2"
  349. v-model.trim="visibleForm.finalSalary"
  350. disabled
  351. type="number"
  352. @mousewheel.native.prevent
  353. ></el-input-number>
  354. </el-form-item>
  355. <el-form-item
  356. label="说明"
  357. :rules="[
  358. { required: true, message: '请填写说明', trigger: 'blur' },
  359. ]"
  360. prop="memo"
  361. >
  362. <el-input
  363. type="textarea"
  364. :rows="5"
  365. v-model.trim="visibleForm.memo"
  366. ></el-input>
  367. </el-form-item>
  368. </el-form>
  369. </div>
  370. <div slot="footer">
  371. <el-button @click="dialogVisible = false">取 消</el-button>
  372. <el-button type="primary" @click="subreset">确 定</el-button>
  373. </div>
  374. </el-dialog>
  375. </div>
  376. </template>
  377. <script>
  378. import numeral from "numeral";
  379. import axios from "axios";
  380. import { getToken } from "@/utils/auth";
  381. import pagination from "@/components/Pagination/index";
  382. import remoteSearch from "@/components/remote-search/index";
  383. import load from "@/utils/loading";
  384. import { belongDaya } from "@/constant";
  385. import { objectToOptions } from "@/utils";
  386. import dayjs from "dayjs";
  387. import {
  388. findIsSettlementCourseSalarys,
  389. openSalaryConfirm,
  390. closeSalaryConfirm,
  391. teacherSalaryModifyLog,
  392. } from "@/api/journal";
  393. import { courseListType } from "@/utils/searchArray";
  394. export default {
  395. components: { pagination, remoteSearch },
  396. data() {
  397. return {
  398. belongDaya,
  399. searchForm: {
  400. search: null,
  401. organIdList: null,
  402. groupType: null,
  403. teacherId: null,
  404. signInStatus: null,
  405. signOutStatus: null,
  406. month: null,
  407. confirmStatus: null,
  408. belongDaya: null,
  409. },
  410. dialogVisible: false,
  411. visibleForm: {
  412. finalSalary: null,
  413. reduceSalary: null,
  414. actualSalary: null,
  415. courseScheduleId: null,
  416. teacherId: null,
  417. memo: null,
  418. },
  419. isOpen: null,
  420. activeRow: null,
  421. tableList: [],
  422. groupTypeList: courseListType,
  423. rules: {
  424. // 分页规则
  425. limit: 10, // 限制显示条数
  426. page: 1, // 当前页
  427. total: 0, // 总条数
  428. page_size: [10, 20, 40, 50], // 选择限制显示条数
  429. },
  430. };
  431. },
  432. //生命周期 - 创建完成(可以访问当前this实例)
  433. created() {
  434. if (!this.searchForm.month) {
  435. var now = new Date();
  436. this.searchForm.month = new Date(
  437. Date.UTC(now.getFullYear(), now.getMonth(), now.getDate())
  438. )
  439. .toISOString()
  440. .slice(0, 7);
  441. }
  442. },
  443. //生命周期 - 挂载完成(可以访问DOM元素)
  444. async mounted() {
  445. await this.$store.dispatch("setBranchs");
  446. await this.$store.dispatch("setTeachers");
  447. // 获取分部
  448. this.init();
  449. },
  450. methods: {
  451. init() {
  452. this.getList();
  453. },
  454. getList() {
  455. let obj = this.getDate();
  456. findIsSettlementCourseSalarys(obj).then((res) => {
  457. if (res.code == 200) {
  458. this.isOpen = res.data.isOpenConfirm;
  459. this.tableList = res.data.pageInfo.rows;
  460. this.rules.total = res.data.pageInfo.total;
  461. }
  462. });
  463. },
  464. search() {
  465. this.rules.page = 1;
  466. this.getList();
  467. },
  468. onReSet() {
  469. this.searchForm = {
  470. search: null,
  471. organIdList: null,
  472. groupType: null,
  473. teacherId: null,
  474. signInStatus: null,
  475. signOutStatus: null,
  476. month: dayjs().format("YYYY-MM"),
  477. confirmStatus: null,
  478. };
  479. this.search();
  480. },
  481. getDate() {
  482. let obj = {
  483. search: this.searchForm.search,
  484. organIdList: this.searchForm.organIdList || null,
  485. groupType: this.searchForm.groupType || null,
  486. teacherId: this.searchForm.teacherId || null,
  487. signInStatus: this.searchForm.signInStatus || null,
  488. signOutStatus: this.searchForm.signOutStatus || null,
  489. month: this.searchForm.month || null,
  490. confirmStatus: this.searchForm.confirmStatus || null,
  491. belongDaya: this.searchForm.belongDaya || null,
  492. page: this.rules.page,
  493. rows: this.rules.limit,
  494. };
  495. return obj;
  496. },
  497. openSalary() {
  498. this.$confirm("您确定开启课酬确认?", "提示", {
  499. confirmButtonText: "确定",
  500. cancelButtonText: "取消",
  501. type: "warning",
  502. }).then(() => {
  503. openSalaryConfirm({ month: this.searchForm.month }).then((res) => {
  504. if (res.code == 200) {
  505. this.$message.success("开启成功");
  506. this.getList();
  507. }
  508. });
  509. });
  510. },
  511. closeSalary() {
  512. this.$confirm("您确定关闭课酬确认?", "提示", {
  513. confirmButtonText: "确定",
  514. cancelButtonText: "取消",
  515. type: "warning",
  516. }).then(() => {
  517. closeSalaryConfirm({ month: this.searchForm.month }).then((res) => {
  518. if (res.code == 200) {
  519. this.$message.success("关闭成功");
  520. this.getList();
  521. }
  522. });
  523. });
  524. },
  525. onExport() {
  526. let url = "/api-web/export/isSettlementCourseSalarys";
  527. let obj = this.getDate();
  528. const options = {
  529. method: "get",
  530. headers: {
  531. Authorization: getToken(),
  532. },
  533. url,
  534. params: obj,
  535. responseType: "blob",
  536. };
  537. this.$confirm("您确定导出列表?", "提示", {
  538. confirmButtonText: "确定",
  539. cancelButtonText: "取消",
  540. type: "warning",
  541. })
  542. .then(() => {
  543. load.startLoading();
  544. axios(options)
  545. .then((res) => {
  546. console.log(res)
  547. let blob = new Blob([res.data], {
  548. // type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8',
  549. type: "application/vnd.ms-excel;charset=utf-8",
  550. // word文档为application/msword,pdf文档为application/pdf,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8
  551. });
  552. let text = new Response(blob).text();
  553. text.then((res) => {
  554. // 判断是否报错
  555. if (res.indexOf("code") != -1) {
  556. let json = JSON.parse(res);
  557. this.$message.error(json.msg);
  558. } else {
  559. let objectUrl = URL.createObjectURL(blob);
  560. let link = document.createElement("a");
  561. let nowTime = new Date();
  562. let ymd =
  563. nowTime.getFullYear() +
  564. "" +
  565. (nowTime.getMonth() + 1) +
  566. "" +
  567. nowTime.getDate() +
  568. "" +
  569. nowTime.getHours() +
  570. "" +
  571. nowTime.getMinutes();
  572. let fname = ymd + "课酬确认.xls";
  573. link.href = objectUrl;
  574. link.setAttribute("download", fname);
  575. document.body.appendChild(link);
  576. link.click();
  577. }
  578. });
  579. load.endLoading();
  580. })
  581. .catch((error) => {
  582. this.$message.error("导出数据失败,请联系管理员");
  583. load.endLoading();
  584. });
  585. })
  586. .catch(() => {});
  587. },
  588. resetSalary(row) {
  589. this.$nextTick(() => {
  590. this.visibleForm = {
  591. finalSalary: row.finalSalary, // 实发
  592. reduceSalary: row.reduceSalary, // 扣款
  593. actualSalary: row.actualSalary, // 应发
  594. courseScheduleId: row.courseScheduleId,
  595. memo: row.memo,
  596. teacherId: row.teacherId,
  597. };
  598. });
  599. // let obj = {
  600. // finalSalary: row.finalSalary, // 实发
  601. // reduceSalary: row.reduceSalary, // 扣款
  602. // actualSalary: row.actualSalary, // 应发
  603. // courseScheduleId: row.courseScheduleId,
  604. // memo: row.memo,
  605. // teacherId: row.teacherId,
  606. // };
  607. // this.$set(this, "visibleForm", obj);
  608. this.dialogVisible = true;
  609. },
  610. subreset() {
  611. this.$refs["visibleForm"].validate((flag) => {
  612. if (flag) {
  613. let obj = {
  614. courseScheduleId: this.visibleForm.courseScheduleId,
  615. currentExpectSalary: this.visibleForm.actualSalary,
  616. currentReduceSalary: this.visibleForm.reduceSalary,
  617. memo: this.visibleForm.memo,
  618. teacherId: this.visibleForm.teacherId,
  619. };
  620. teacherSalaryModifyLog(obj).then((res) => {
  621. if (res.code == 200) {
  622. this.dialogVisible = false;
  623. this.$message.success("调整成功");
  624. this.getList();
  625. }
  626. });
  627. }
  628. });
  629. },
  630. },
  631. filters: {
  632. confirmFilter(val) {
  633. if (val) {
  634. let template = {
  635. 1: "待确认",
  636. 2: "已确认",
  637. 3: "已完成",
  638. };
  639. return template[val];
  640. }
  641. },
  642. },
  643. computed: {
  644. getActualsalary() {
  645. // 应发
  646. return this.visibleForm.actualSalary;
  647. },
  648. getReduceSalary() {
  649. // 扣款
  650. return this.visibleForm.reduceSalary;
  651. },
  652. belongDayaOption() {
  653. return objectToOptions(belongDaya);
  654. },
  655. },
  656. watch: {
  657. getActualsalary(val) {
  658. var number = numeral(val);
  659. this.visibleForm.finalSalary = Math.max(
  660. number.subtract(this.getReduceSalary).value(),
  661. 0
  662. );
  663. },
  664. getReduceSalary(val) {
  665. var number = numeral(this.getActualsalary);
  666. this.visibleForm.finalSalary = Math.max(number.subtract(val).value(), 0);
  667. },
  668. dialogVisible(val) {
  669. if (!val) {
  670. // this.visibleForm = {
  671. // expectSalary: null,
  672. // reduceSalary: null,
  673. // actualSalary: null,
  674. // courseScheduleId: null,
  675. // teacherId: null,
  676. // memo: null,
  677. // };
  678. this.$refs["visibleForm"].resetFields();
  679. }
  680. },
  681. },
  682. };
  683. </script>
  684. <style lang='scss' scoped>
  685. .red {
  686. color: red;
  687. }
  688. .visibleForm {
  689. /deep/.el-input__inner,
  690. /deep/.el-textarea__inner {
  691. width: 225px !important;
  692. }
  693. }
  694. /deep/.el-input-number .el-input__inner {
  695. text-align: left;
  696. }
  697. </style>