classFeesIsOk.vue 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694
  1. <!-- -->
  2. <template>
  3. <div class="m-container">
  4. <h2>
  5. <div class="squrt"></div>
  6. 课酬确认
  7. </h2>
  8. <div class="m-core">
  9. <div
  10. @click="openSalary"
  11. v-if="isOpen == 0"
  12. v-permission="'courseScheduleTeacherSalary/openSalaryConfirm'"
  13. class="newBand"
  14. >
  15. 开启课酬确认
  16. </div>
  17. <div
  18. v-if="isOpen == 1"
  19. @click="closeSalary"
  20. v-permission="'courseScheduleTeacherSalary/closeSalaryConfirm'"
  21. class="newBand"
  22. >
  23. 关闭课酬确认
  24. </div>
  25. <save-form
  26. :inline="true"
  27. @submit="search"
  28. @reset="onReSet"
  29. :model="searchForm"
  30. >
  31. <el-form-item>
  32. <el-input
  33. v-model.trim="searchForm.search"
  34. @keyup.enter.native="search"
  35. clearable
  36. placeholder="课程编号、课程组名称"
  37. ></el-input>
  38. </el-form-item>
  39. <el-form-item prop="organId">
  40. <el-select
  41. class="multiple"
  42. v-model.trim="searchForm.organIdList"
  43. filterable
  44. clearable
  45. placeholder="请选择分部"
  46. >
  47. <el-option
  48. v-for="(item, index) in selects.branchs"
  49. :key="index"
  50. :label="item.name"
  51. :value="item.id"
  52. ></el-option>
  53. </el-select>
  54. </el-form-item>
  55. <el-form-item prop="organId">
  56. <el-select
  57. class="multiple"
  58. v-model.trim="searchForm.groupType"
  59. filterable
  60. clearable
  61. placeholder="请选择课程组类型"
  62. >
  63. <el-option
  64. v-for="(item, index) in groupTypeList"
  65. :key="index"
  66. :label="item.label"
  67. :value="item.value"
  68. ></el-option>
  69. </el-select>
  70. </el-form-item>
  71. <el-form-item prop="belongDaya">
  72. <el-select
  73. v-model.trim="searchForm.belongDaya"
  74. clearable
  75. placeholder="请选择课酬类型"
  76. >
  77. <el-option
  78. v-for="(item, index) in belongDayaOption"
  79. :key="index"
  80. :label="item.label"
  81. :value="item.value"
  82. ></el-option>
  83. </el-select>
  84. </el-form-item>
  85. <el-form-item>
  86. <remoteSearch :commit='"setTeachers"' v-model='searchForm.teacherId' />
  87. <!-- <el-select
  88. placeholder="老师姓名"
  89. v-model="searchForm.teacherId"
  90. clearable
  91. filterable
  92. >
  93. <el-option
  94. v-for="(item, index) in selects.teachers"
  95. :label="item.realName"
  96. :value="item.id"
  97. :key="index"
  98. ></el-option>
  99. </el-select> -->
  100. </el-form-item>
  101. <el-form-item>
  102. <el-select
  103. placeholder="正常签到"
  104. v-model="searchForm.signInStatus"
  105. clearable
  106. >
  107. <el-option label="是" value="1"></el-option>
  108. <el-option label="否" value="0"></el-option>
  109. </el-select>
  110. </el-form-item>
  111. <el-form-item>
  112. <el-select
  113. placeholder="正常签退"
  114. v-model="searchForm.signOutStatus"
  115. clearable
  116. >
  117. <el-option label="是" value="1"></el-option>
  118. <el-option label="否" value="0"></el-option>
  119. </el-select>
  120. </el-form-item>
  121. <el-form-item>
  122. <el-select
  123. placeholder="状态"
  124. v-model="searchForm.confirmStatus"
  125. clearable
  126. >
  127. <el-option label="待确定" value="1"></el-option>
  128. <el-option label="已确定" value="2"></el-option>
  129. <el-option label="已完成" value="3"></el-option>
  130. </el-select>
  131. </el-form-item>
  132. <el-form-item>
  133. <el-date-picker
  134. :clearable="false"
  135. v-model="searchForm.month"
  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
  253. align="center"
  254. prop="belongDaya"
  255. label="课酬类型"
  256. >
  257. <template slot-scope="scope">{{
  258. belongDaya[scope.row.belongDaya]
  259. }}</template>
  260. </el-table-column>
  261. <el-table-column align="center" prop="actualSalary" label="应发课酬">
  262. <template slot-scope="scope"
  263. >{{ scope.row.actualSalary | moneyFormat }}元</template
  264. >
  265. </el-table-column>
  266. <el-table-column align="center" prop="reduceSalary" label="课酬扣款">
  267. <template slot-scope="scope"
  268. >{{ scope.row.reduceSalary | moneyFormat }}元</template
  269. >
  270. </el-table-column>
  271. <el-table-column align="center" prop="finalSalary" label="结算课酬">
  272. <template slot-scope="scope"
  273. >{{ scope.row.finalSalary | moneyFormat }}元</template
  274. >
  275. </el-table-column>
  276. <el-table-column align="center" prop label="状态" fixed="right">
  277. <template slot-scope="scope">{{
  278. scope.row.confirmStatus | confirmFilter
  279. }}</template>
  280. </el-table-column>
  281. <el-table-column
  282. align="center"
  283. prop="memo"
  284. label="备注"
  285. width="300"
  286. fixed="right"
  287. ></el-table-column>
  288. <el-table-column align="center" label="操作" fixed="right">
  289. <template slot-scope="scope">
  290. <el-button type="text" @click="resetSalary(scope.row)"
  291. >课酬调整</el-button
  292. >
  293. </template>
  294. </el-table-column>
  295. </el-table>
  296. <pagination
  297. sync
  298. :total.sync="rules.total"
  299. :page.sync="rules.page"
  300. :limit.sync="rules.limit"
  301. :page-sizes="rules.page_size"
  302. @pagination="getList"
  303. />
  304. </div>
  305. </div>
  306. <el-dialog title="课酬调整" :visible.sync="dialogVisible" width="400px">
  307. <div>
  308. <el-form
  309. ref="visibleForm"
  310. :model="visibleForm"
  311. class="visibleForm"
  312. :inline="true"
  313. label-width="60px"
  314. >
  315. <el-form-item
  316. label="应发"
  317. :rules="[
  318. { required: true, message: '请填写应发数', trigger: 'blur' },
  319. ]"
  320. prop="actualSalary"
  321. >
  322. <el-input-number
  323. :controls="false"
  324. :min="0"
  325. :precision="2"
  326. v-model.trim="visibleForm.actualSalary"
  327. type="number"
  328. @mousewheel.native.prevent
  329. ></el-input-number>
  330. </el-form-item>
  331. <el-form-item
  332. label="扣款"
  333. :rules="[
  334. { required: true, message: '请填写扣款数', trigger: 'blur' },
  335. ]"
  336. prop="reduceSalary"
  337. >
  338. <el-input-number
  339. :controls="false"
  340. :min="0"
  341. :precision="2"
  342. v-model.trim="visibleForm.reduceSalary"
  343. type="number"
  344. @mousewheel.native.prevent
  345. ></el-input-number>
  346. </el-form-item>
  347. <el-form-item label="实发">
  348. <el-input-number
  349. :controls="false"
  350. :min="0"
  351. :precision="2"
  352. v-model.trim="visibleForm.finalSalary"
  353. disabled
  354. type="number"
  355. @mousewheel.native.prevent
  356. ></el-input-number>
  357. </el-form-item>
  358. <el-form-item
  359. label="说明"
  360. :rules="[
  361. { required: true, message: '请填写说明', trigger: 'blur' },
  362. ]"
  363. prop="memo"
  364. >
  365. <el-input
  366. type="textarea"
  367. :rows="5"
  368. v-model.trim="visibleForm.memo"
  369. ></el-input>
  370. </el-form-item>
  371. </el-form>
  372. </div>
  373. <div slot="footer">
  374. <el-button @click="dialogVisible = false">取 消</el-button>
  375. <el-button type="primary" @click="subreset">确 定</el-button>
  376. </div>
  377. </el-dialog>
  378. </div>
  379. </template>
  380. <script>
  381. import numeral from "numeral";
  382. import axios from "axios";
  383. import { getToken } from "@/utils/auth";
  384. import pagination from "@/components/Pagination/index";
  385. import remoteSearch from '@/components/remote-search/index'
  386. import load from "@/utils/loading";
  387. import { belongDaya } from '@/constant'
  388. import { objectToOptions } from '@/utils'
  389. import {
  390. findIsSettlementCourseSalarys,
  391. openSalaryConfirm,
  392. closeSalaryConfirm,
  393. teacherSalaryModifyLog,
  394. } from "@/api/journal";
  395. import { courseListType } from "@/utils/searchArray";
  396. export default {
  397. components: { pagination, remoteSearch },
  398. data() {
  399. return {
  400. belongDaya,
  401. searchForm: {
  402. search: null,
  403. organIdList: null,
  404. groupType: null,
  405. teacherId: null,
  406. signInStatus: null,
  407. signOutStatus: null,
  408. month: null,
  409. confirmStatus: null,
  410. belongDaya: null,
  411. },
  412. dialogVisible: false,
  413. visibleForm: {
  414. finalSalary: null,
  415. reduceSalary: null,
  416. actualSalary: null,
  417. courseScheduleId: null,
  418. teacherId: null,
  419. memo: null,
  420. },
  421. isOpen: null,
  422. activeRow: null,
  423. tableList: [],
  424. groupTypeList: courseListType,
  425. rules: {
  426. // 分页规则
  427. limit: 10, // 限制显示条数
  428. page: 1, // 当前页
  429. total: 0, // 总条数
  430. page_size: [10, 20, 40, 50], // 选择限制显示条数
  431. },
  432. };
  433. },
  434. //生命周期 - 创建完成(可以访问当前this实例)
  435. created() {},
  436. //生命周期 - 挂载完成(可以访问DOM元素)
  437. async mounted() {
  438. await this.$store.dispatch('setBranchs')
  439. await this.$store.dispatch('setTeachers')
  440. // 获取分部
  441. this.init();
  442. },
  443. methods: {
  444. init() {
  445. if (!this.searchForm.month) {
  446. var now = new Date();
  447. this.searchForm.month = new Date(
  448. Date.UTC(now.getFullYear(), now.getMonth(), now.getDate())
  449. )
  450. .toISOString()
  451. .slice(0, 7);
  452. }
  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: null,
  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 + "课酬确认";
  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. let obj = {
  590. finalSalary: row.finalSalary, // 实发
  591. reduceSalary: row.reduceSalary, // 扣款
  592. actualSalary: row.actualSalary, // 应发
  593. courseScheduleId: row.courseScheduleId,
  594. memo: row.memo,
  595. teacherId: row.teacherId,
  596. };
  597. this.$set(this, "visibleForm", obj);
  598. console.log(this.visibleForm.finalSalary);
  599. this.dialogVisible = true;
  600. },
  601. subreset() {
  602. this.$refs["visibleForm"].validate((flag) => {
  603. if (flag) {
  604. let obj = {
  605. courseScheduleId: this.visibleForm.courseScheduleId,
  606. currentExpectSalary: this.visibleForm.actualSalary,
  607. currentReduceSalary: this.visibleForm.reduceSalary,
  608. memo: this.visibleForm.memo,
  609. teacherId: this.visibleForm.teacherId,
  610. };
  611. teacherSalaryModifyLog(obj).then((res) => {
  612. if (res.code == 200) {
  613. this.dialogVisible = false;
  614. this.$message.success("调整成功");
  615. this.getList();
  616. }
  617. });
  618. }
  619. });
  620. },
  621. },
  622. filters: {
  623. confirmFilter(val) {
  624. if (val) {
  625. let template = {
  626. 1: "待确认",
  627. 2: "已确认",
  628. 3: "已完成",
  629. };
  630. return template[val];
  631. }
  632. },
  633. },
  634. computed: {
  635. getActualsalary() {
  636. // 应发
  637. return this.visibleForm.actualSalary;
  638. },
  639. getReduceSalary() {
  640. // 扣款
  641. return this.visibleForm.reduceSalary;
  642. },
  643. belongDayaOption() {
  644. return objectToOptions(belongDaya)
  645. }
  646. },
  647. watch: {
  648. getActualsalary(val) {
  649. var number = numeral(val);
  650. this.visibleForm.finalSalary = Math.max(
  651. number.subtract(this.getReduceSalary).value(),
  652. 0
  653. );
  654. },
  655. getReduceSalary(val) {
  656. var number = numeral(this.getActualsalary);
  657. this.visibleForm.finalSalary = Math.max(number.subtract(val).value(), 0);
  658. },
  659. dialogVisible(val) {
  660. if (!val) {
  661. this.visibleForm = {
  662. expectSalary: null,
  663. reduceSalary: null,
  664. actualSalary: null,
  665. courseScheduleId: null,
  666. teacherId: null,
  667. memo: null,
  668. };
  669. this.$refs["visibleForm"].resetFields();
  670. }
  671. },
  672. },
  673. };
  674. </script>
  675. <style lang='scss' scoped>
  676. .red {
  677. color: red;
  678. }
  679. .visibleForm {
  680. /deep/.el-input__inner,
  681. /deep/.el-textarea__inner {
  682. width: 225px !important;
  683. }
  684. }
  685. /deep/.el-input-number .el-input__inner {
  686. text-align: left;
  687. }
  688. </style>