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/exercisesSituations'"
  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="状态" fixed="right">
  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. fixed="right"
  283. ></el-table-column>
  284. <el-table-column align="center" label="操作" fixed="right">
  285. <template slot-scope="scope">
  286. <auth auths='teacherSalaryModifyLog/add'>
  287. <el-button type="text" @click="resetSalary(scope.row)"
  288. >课酬调整</el-button
  289. >
  290. </auth>
  291. </template>
  292. </el-table-column>
  293. </el-table>
  294. <pagination
  295. sync
  296. :total.sync="rules.total"
  297. :page.sync="rules.page"
  298. :limit.sync="rules.limit"
  299. :page-sizes="rules.page_size"
  300. @pagination="getList"
  301. />
  302. </div>
  303. </div>
  304. <el-dialog title="课酬调整" :visible.sync="dialogVisible" width="400px">
  305. <div>
  306. <el-form
  307. ref="visibleForm"
  308. :model="visibleForm"
  309. class="visibleForm"
  310. :inline="true"
  311. label-width="60px"
  312. >
  313. <el-form-item
  314. label="应发"
  315. :rules="[
  316. { required: true, message: '请填写应发数', trigger: 'blur' },
  317. ]"
  318. prop="actualSalary"
  319. >
  320. <el-input-number
  321. :controls="false"
  322. :min="0"
  323. :precision="2"
  324. v-model.trim="visibleForm.actualSalary"
  325. type="number"
  326. @mousewheel.native.prevent
  327. ></el-input-number>
  328. </el-form-item>
  329. <el-form-item
  330. label="扣款"
  331. :rules="[
  332. { required: true, message: '请填写扣款数', trigger: 'blur' },
  333. ]"
  334. prop="reduceSalary"
  335. >
  336. <el-input-number
  337. :controls="false"
  338. :min="0"
  339. :precision="2"
  340. v-model.trim="visibleForm.reduceSalary"
  341. type="number"
  342. @mousewheel.native.prevent
  343. ></el-input-number>
  344. </el-form-item>
  345. <el-form-item label="实发">
  346. <el-input-number
  347. :controls="false"
  348. :min="0"
  349. :precision="2"
  350. v-model.trim="visibleForm.finalSalary"
  351. disabled
  352. type="number"
  353. @mousewheel.native.prevent
  354. ></el-input-number>
  355. </el-form-item>
  356. <el-form-item
  357. label="说明"
  358. :rules="[
  359. { required: true, message: '请填写说明', trigger: 'blur' },
  360. ]"
  361. prop="memo"
  362. >
  363. <el-input
  364. type="textarea"
  365. :rows="5"
  366. v-model.trim="visibleForm.memo"
  367. ></el-input>
  368. </el-form-item>
  369. </el-form>
  370. </div>
  371. <div slot="footer">
  372. <el-button @click="dialogVisible = false">取 消</el-button>
  373. <el-button type="primary" @click="subreset">确 定</el-button>
  374. </div>
  375. </el-dialog>
  376. </div>
  377. </template>
  378. <script>
  379. import numeral from "numeral";
  380. import axios from "axios";
  381. import { getToken } from "@/utils/auth";
  382. import pagination from "@/components/Pagination/index";
  383. import remoteSearch from "@/components/remote-search/index";
  384. import load from "@/utils/loading";
  385. import { belongDaya } from "@/constant";
  386. import { objectToOptions } from "@/utils";
  387. import dayjs from "dayjs";
  388. import {
  389. findIsSettlementCourseSalarys,
  390. openSalaryConfirm,
  391. closeSalaryConfirm,
  392. teacherSalaryModifyLog,
  393. } from "@/api/journal";
  394. import { courseListType } from "@/utils/searchArray";
  395. export default {
  396. components: { pagination, remoteSearch },
  397. data() {
  398. return {
  399. belongDaya,
  400. searchForm: {
  401. search: null,
  402. organIdList: null,
  403. groupType: null,
  404. teacherId: null,
  405. signInStatus: null,
  406. signOutStatus: null,
  407. month: null,
  408. confirmStatus: null,
  409. belongDaya: null,
  410. },
  411. dialogVisible: false,
  412. visibleForm: {
  413. finalSalary: null,
  414. reduceSalary: null,
  415. actualSalary: null,
  416. courseScheduleId: null,
  417. teacherId: null,
  418. memo: null,
  419. },
  420. isOpen: null,
  421. activeRow: null,
  422. tableList: [],
  423. groupTypeList: courseListType,
  424. rules: {
  425. // 分页规则
  426. limit: 10, // 限制显示条数
  427. page: 1, // 当前页
  428. total: 0, // 总条数
  429. page_size: [10, 20, 40, 50], // 选择限制显示条数
  430. },
  431. };
  432. },
  433. //生命周期 - 创建完成(可以访问当前this实例)
  434. created() {
  435. if (!this.searchForm.month) {
  436. var now = new Date();
  437. this.searchForm.month = new Date(
  438. Date.UTC(now.getFullYear(), now.getMonth(), now.getDate())
  439. )
  440. .toISOString()
  441. .slice(0, 7);
  442. }
  443. },
  444. //生命周期 - 挂载完成(可以访问DOM元素)
  445. async mounted() {
  446. await this.$store.dispatch("setBranchs");
  447. await this.$store.dispatch("setTeachers");
  448. // 获取分部
  449. this.init();
  450. },
  451. methods: {
  452. init() {
  453. this.getList();
  454. },
  455. getList() {
  456. let obj = this.getDate();
  457. findIsSettlementCourseSalarys(obj).then((res) => {
  458. if (res.code == 200) {
  459. this.isOpen = res.data.isOpenConfirm;
  460. this.tableList = res.data.pageInfo.rows;
  461. this.rules.total = res.data.pageInfo.total;
  462. }
  463. });
  464. },
  465. search() {
  466. this.rules.page = 1;
  467. this.getList();
  468. },
  469. onReSet() {
  470. this.searchForm = {
  471. search: null,
  472. organIdList: null,
  473. groupType: null,
  474. teacherId: null,
  475. signInStatus: null,
  476. signOutStatus: null,
  477. month: dayjs().format("YYYY-MM"),
  478. confirmStatus: null,
  479. };
  480. this.search();
  481. },
  482. getDate() {
  483. let obj = {
  484. search: this.searchForm.search,
  485. organIdList: this.searchForm.organIdList || null,
  486. groupType: this.searchForm.groupType || null,
  487. teacherId: this.searchForm.teacherId || null,
  488. signInStatus: this.searchForm.signInStatus || null,
  489. signOutStatus: this.searchForm.signOutStatus || null,
  490. month: this.searchForm.month || null,
  491. confirmStatus: this.searchForm.confirmStatus || null,
  492. belongDaya: this.searchForm.belongDaya || null,
  493. page: this.rules.page,
  494. rows: this.rules.limit,
  495. };
  496. return obj;
  497. },
  498. openSalary() {
  499. this.$confirm("您确定开启课酬确认?", "提示", {
  500. confirmButtonText: "确定",
  501. cancelButtonText: "取消",
  502. type: "warning",
  503. }).then(() => {
  504. openSalaryConfirm({ month: this.searchForm.month }).then((res) => {
  505. if (res.code == 200) {
  506. this.$message.success("开启成功");
  507. this.getList();
  508. }
  509. });
  510. });
  511. },
  512. closeSalary() {
  513. this.$confirm("您确定关闭课酬确认?", "提示", {
  514. confirmButtonText: "确定",
  515. cancelButtonText: "取消",
  516. type: "warning",
  517. }).then(() => {
  518. closeSalaryConfirm({ month: this.searchForm.month }).then((res) => {
  519. if (res.code == 200) {
  520. this.$message.success("关闭成功");
  521. this.getList();
  522. }
  523. });
  524. });
  525. },
  526. onExport() {
  527. let url = "/api-web/export/isSettlementCourseSalarys";
  528. let obj = this.getDate();
  529. const options = {
  530. method: "get",
  531. headers: {
  532. Authorization: getToken(),
  533. },
  534. url,
  535. params: obj,
  536. responseType: "blob",
  537. };
  538. this.$confirm("您确定导出列表?", "提示", {
  539. confirmButtonText: "确定",
  540. cancelButtonText: "取消",
  541. type: "warning",
  542. })
  543. .then(() => {
  544. load.startLoading();
  545. axios(options)
  546. .then((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>