index.vue 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736
  1. <template>
  2. <div class="page-container list-container">
  3. <!-- 功能按钮区 -->
  4. <div class="list-btns-container">
  5. <!-- <el-button type="danger" size="small" icon="Delete" :disabled="multiple" @click="handleDelete"
  6. v-hasPermi="['business:workOrder:remove']">删除</el-button> -->
  7. <el-dropdown>
  8. <el-button type="primary" size="small">
  9. 其它<el-icon class="el-icon--right"><arrow-down /></el-icon>
  10. </el-button>
  11. <template #dropdown>
  12. <el-dropdown-menu>
  13. <el-dropdown-item
  14. icon="Download"
  15. @click="handleExport"
  16. v-hasPermi="['business:customer:service:loop:export']"
  17. >
  18. 导出</el-dropdown-item
  19. >
  20. <el-dropdown-item
  21. icon="Operation"
  22. @click="setServiceHandler"
  23. v-hasPermi="['business:customer:service:loop:transactor']"
  24. >
  25. 设置执行人</el-dropdown-item
  26. >
  27. </el-dropdown-menu>
  28. </template>
  29. </el-dropdown>
  30. </div>
  31. <!-- 搜索区 -->
  32. <el-form
  33. class="list-search-container"
  34. size="small"
  35. :model="queryParams"
  36. ref="queryRef"
  37. :inline="true"
  38. label-width="68px"
  39. >
  40. <el-form-item label="客户名称:" prop="companyName">
  41. <el-input
  42. style="width: 150px"
  43. v-model="queryParams.companyName"
  44. placeholder="请输入客户名称"
  45. clearable
  46. @keyup.enter="handleQuery"
  47. />
  48. </el-form-item>
  49. <el-form-item label="月份:" prop="month">
  50. <el-select
  51. v-model.trim="queryParams.month"
  52. size="small"
  53. placeholder="月份"
  54. :clearable="true"
  55. style="width: 130px"
  56. @change="handleQuery"
  57. >
  58. <el-option
  59. v-for="item in selectMonths"
  60. :key="item.value"
  61. :label="item.label"
  62. :value="item.value"
  63. />
  64. </el-select>
  65. </el-form-item>
  66. <el-form-item label="状态:" prop="status">
  67. <el-select
  68. v-model.trim="queryParams.status"
  69. size="small"
  70. type="text"
  71. placeholder="状态"
  72. :clearable="true"
  73. style="width: 130px"
  74. @clear="clearStatus"
  75. >
  76. <el-option
  77. v-for="item in selectStatus"
  78. :key="item.value"
  79. :label="item.label"
  80. :value="item.value"
  81. />
  82. </el-select>
  83. </el-form-item>
  84. <el-form-item>
  85. <el-button type="primary" icon="Search" @click="handleQuery"
  86. >搜索</el-button
  87. >
  88. <el-button icon="Refresh" @click="resetQuery">重置</el-button>
  89. </el-form-item>
  90. </el-form>
  91. <!-- 列表区 -->
  92. <el-table
  93. v-loading="loading"
  94. :data="serviceList"
  95. size="small"
  96. border
  97. height="100%"
  98. @selection-change="handleSelectionChange"
  99. >
  100. <el-table-column type="selection" width="55" align="center" />
  101. <el-table-column
  102. label="客户名称"
  103. align="center"
  104. min-width="250"
  105. prop="companyName"
  106. />
  107. <el-table-column
  108. label="纳税性质"
  109. min-width="100"
  110. align="center"
  111. prop="taxType"
  112. />
  113. <el-table-column
  114. label="税号"
  115. align="center"
  116. prop="socialCreditCode"
  117. min-width="180"
  118. />
  119. <el-table-column
  120. label="项目"
  121. align="center"
  122. prop="taskTypeName"
  123. min-width="90"
  124. >
  125. <template #default="scope">
  126. {{ scope.row.taskTypeName }}
  127. </template>
  128. </el-table-column>
  129. <el-table-column label="当前期间" width="90" align="center">
  130. <template #default="scope">
  131. <!-- {{ scope.row.currentDate != null && scope.row.currentDate > scope.row.checkoutDate ? scope.row.currentDate :
  132. scope.row.checkoutDate }} -->
  133. {{
  134. scope.row.taskTypeId === "1"
  135. ? moment().subtract(1, "month").format("YYYY年MM月")
  136. : moment().format("YYYY年MM月")
  137. }}
  138. </template>
  139. </el-table-column>
  140. <el-table-column align="center">
  141. <template #header>
  142. <div
  143. style="
  144. display: flex;
  145. flex-direction: row;
  146. justify-content: space-between;
  147. "
  148. >
  149. <div style="display: flex; flex-direction: row">
  150. <el-button
  151. link
  152. type="primary"
  153. size="small"
  154. icon="ArrowLeft"
  155. @click="prevYear"
  156. />
  157. <el-link style="margin: 0 40px" :underline="false">{{
  158. queryParams.year
  159. }}</el-link>
  160. <el-button
  161. link
  162. type="primary"
  163. icon="ArrowRight"
  164. size="small"
  165. @click="nextYear"
  166. />
  167. </div>
  168. <div style="display: flex; flex-direction: row; margin-right: 20px">
  169. <div
  170. v-for="item in selectStatus"
  171. :key="item.value"
  172. style="display: flex; flex-direction: row; margin-right: 10px"
  173. >
  174. <div
  175. :style="{
  176. backgroundColor: item.color,
  177. width: '14px',
  178. height: '14px',
  179. margin: 'auto',
  180. borderRadius: '50%',
  181. border: item.color === '#fff' ? '1px solid #ddd' : 'none',
  182. }"
  183. />
  184. <div
  185. style="
  186. display: inline-block;
  187. margin-left: 10px;
  188. line-height: 36px;
  189. "
  190. >
  191. {{ item.label }}
  192. </div>
  193. </div>
  194. </div>
  195. </div>
  196. </template>
  197. <el-table-column
  198. v-for="item in selectMonths"
  199. :key="item.value"
  200. min-width="50"
  201. :label="item.label"
  202. align="center"
  203. >
  204. <template #default="scope">
  205. <el-button
  206. size="small"
  207. :style="monthStatusStyle(scope.row, item.value)"
  208. circle
  209. @click="handleByRow(scope.row, item.value)"
  210. />
  211. </template>
  212. </el-table-column>
  213. </el-table-column>
  214. <el-table-column label="工单执行人" align="center" min-width="100">
  215. <template #default="scope">{{ getTransactor(scope.row) }}</template>
  216. </el-table-column>
  217. </el-table>
  218. <!-- </div>
  219. </div> -->
  220. <!-- <workorder-form ref="workOrderRef" :get-list="getList" /> -->
  221. <el-dialog
  222. title="新增工单"
  223. v-model="formOpen"
  224. width="500px"
  225. append-to-body
  226. draggable
  227. >
  228. <el-form ref="dictRef" :model="form" label-width="100">
  229. <el-row :gutter="30">
  230. <el-col :span="24">
  231. <el-form-item label="客户名称" prop="companyName">
  232. <el-autocomplete
  233. :fetch-suggestions="querySearchCompanyAsync"
  234. :trigger-on-focus="true"
  235. v-model="form.companyName"
  236. placeholder="请输入客户名称"
  237. popper-class="my-autocomplete"
  238. @select="handleSelectCompany"
  239. >
  240. <template #default="{ item }">
  241. <div
  242. style="
  243. display: flex;
  244. flex-direction: row;
  245. justify-content: space-between;
  246. "
  247. >
  248. <div class="name" style="font-size: 12px">
  249. {{ item.name }}
  250. </div>
  251. <!-- <span class="code" style="font-size: 10px; color: darkgrey;">{{ item.code }}</span> -->
  252. </div>
  253. </template>
  254. </el-autocomplete>
  255. </el-form-item>
  256. </el-col>
  257. <el-col :span="24">
  258. <el-form-item label="备注:">
  259. <el-input
  260. v-model.trim="form.remark"
  261. type="textarea"
  262. width="100%"
  263. size="small"
  264. placeholder="备注"
  265. :clearable="true"
  266. />
  267. </el-form-item>
  268. </el-col>
  269. </el-row>
  270. </el-form>
  271. <template #footer>
  272. <div class="dialog-footer">
  273. <el-button type="primary" @click="saveHandler">确 定</el-button>
  274. <el-button @click="formCancel">取 消</el-button>
  275. </div>
  276. </template>
  277. </el-dialog>
  278. <!-- 分页 -->
  279. <pagination
  280. v-show="total > 0"
  281. :total="total"
  282. v-model:page="queryParams.pageNum"
  283. v-model:limit="queryParams.pageSize"
  284. @pagination="getList"
  285. />
  286. <service-form ref="serviceRef" :get-list="getList" />
  287. <housing-fund-form ref="housingFundFormRef" :get-list="getList" />
  288. <housing-fund-view ref="housingFundViewRef" :get-list="getList" />
  289. <keep-account-form ref="keepAccountFormRef" :get-list="getList" />
  290. <keep-account-view ref="keepAccountViewRef" :get-list="getList" />
  291. <social-security-form ref="socialSecurityFormRef" :get-list="getList" />
  292. <social-security-view ref="socialSecurityViewRef" :get-list="getList" />
  293. </div>
  294. </template>
  295. <script setup name="Company">
  296. // import contractForm from "./form";
  297. import { listLoop } from "@/api/business/crm/serviceWorkOrder";
  298. import { listCompany } from "@/api/business/crm/company";
  299. import serviceForm from "../serviceForm";
  300. import { reactive, ref, toRefs } from "vue";
  301. import KeepAccountView from "./keepAccountView.vue";
  302. import KeepAccountForm from "./keepAccountForm.vue";
  303. import HousingFundForm from "./housingFundForm.vue";
  304. import HousingFundView from "./housingFundView.vue";
  305. import SocialSecurityForm from "./socialSecurityForm.vue";
  306. import SocialSecurityView from "./socialSecurityView.vue";
  307. import useUserStore from "@/store/modules/user";
  308. const permissions = useUserStore().permissions;
  309. const all_permission = "*:*:*";
  310. // import workorderForm from "./form"
  311. const { proxy } = getCurrentInstance();
  312. /** 字典数组区 */
  313. /** 查询 对象 */
  314. const serviceList = ref([]);
  315. const loading = ref(true);
  316. const ids = ref([]);
  317. const single = ref(true);
  318. const multiple = ref(true);
  319. const total = ref(0);
  320. const prev = ref([]);
  321. const keepAccountFormRef = ref(null);
  322. const keepAccountViewRef = ref(null);
  323. const socialSecurityFormRef = ref(null);
  324. const socialSecurityViewRef = ref(null);
  325. const housingFundFormRef = ref(null);
  326. const housingFundViewRef = ref(null);
  327. const data = reactive({
  328. selectMonths: [
  329. {
  330. label: "一月",
  331. value: "01",
  332. },
  333. {
  334. label: "二月",
  335. value: "02",
  336. },
  337. {
  338. label: "三月",
  339. value: "03",
  340. },
  341. {
  342. label: "四月",
  343. value: "04",
  344. },
  345. {
  346. label: "五月",
  347. value: "05",
  348. },
  349. {
  350. label: "六月",
  351. value: "06",
  352. },
  353. {
  354. label: "七月",
  355. value: "07",
  356. },
  357. {
  358. label: "八月",
  359. value: "08",
  360. },
  361. {
  362. label: "九月",
  363. value: "09",
  364. },
  365. {
  366. label: "十月",
  367. value: "10",
  368. },
  369. {
  370. label: "十一月",
  371. value: "11",
  372. },
  373. {
  374. label: "十二月",
  375. value: "12",
  376. },
  377. ],
  378. selectStatus: [
  379. {
  380. label: "未开始",
  381. value: 0,
  382. color: "#fff",
  383. },
  384. {
  385. label: "进行中",
  386. value: 1,
  387. color: "#FFB836",
  388. },
  389. {
  390. label: "已完成",
  391. value: 3,
  392. color: "#2FCB81",
  393. },
  394. ],
  395. });
  396. const { selectStatus, selectMonths } = toRefs(data);
  397. const formOpen = ref(false);
  398. const form = ref({
  399. id: null,
  400. companyName: "",
  401. companyId: null,
  402. remark: "",
  403. type: 1,
  404. });
  405. const emptyForm = {
  406. id: null,
  407. companyName: "",
  408. companyId: null,
  409. type: 2,
  410. remark: "",
  411. noContract: 1,
  412. };
  413. /** 查询对象 */
  414. const queryParams = ref({
  415. pageNum: 1,
  416. pageSize: 10,
  417. orderByColumn: "create_time",
  418. year: proxy.moment().format("YYYY"),
  419. companyName: "",
  420. type: 1,
  421. });
  422. const editStatus = {
  423. startMonth: false,
  424. };
  425. /*********************** 方法区 ****************************/
  426. /** 查询company列表 */
  427. function getList() {
  428. loading.value = true;
  429. listLoop(queryParams.value).then((response) => {
  430. serviceList.value = response.rows;
  431. total.value = response.total;
  432. loading.value = false;
  433. });
  434. }
  435. /** 搜索按钮操作 */
  436. function handleQuery() {
  437. queryParams.value.pageNum = 1;
  438. getList();
  439. }
  440. /** 重置按钮操作 */
  441. function resetQuery() {
  442. proxy.resetForm("queryRef");
  443. handleQuery();
  444. }
  445. // 多选框选中数据
  446. function handleSelectionChange(selection) {
  447. ids.value = selection.map((item) => item.id);
  448. single.value = selection.length != 1;
  449. multiple.value = !selection.length;
  450. }
  451. /** 新增按钮操作 */
  452. function handleAdd() {
  453. // proxy.$refs.workOrderRef.open();
  454. formOpen.value = true;
  455. }
  456. function formCancel() {
  457. formOpen.value = false;
  458. reset();
  459. }
  460. function reset() {
  461. form.value = proxy.deepClone(emptyForm);
  462. }
  463. /** 修改按钮操作 */
  464. function handleUpdate(row) {
  465. // const id = row.id || ids.value;
  466. // proxy.$refs.workOrderRef.open(id);
  467. }
  468. /** 导出按钮操作 */
  469. function handleExport() {
  470. // exportWorkOrder(queryParams.value)
  471. }
  472. function startDateChangeHandler(row, startDate) {
  473. if (startDate) {
  474. row.endMonth = proxy
  475. .moment(startDate)
  476. .add(row.monthNum - 1, "M")
  477. .format("YYYY-MM-DD");
  478. } else row.endMonth = null;
  479. console.log(row);
  480. }
  481. function querySearchCompanyAsync(queryString, cb) {
  482. const query =
  483. queryString.length > 0
  484. ? {
  485. keyword: queryString,
  486. pageSize: 20,
  487. pageNum: 1,
  488. orderByColumn: "create_time",
  489. }
  490. : { pageSize: 20, pageNum: 1, orderByColumn: "create_time" };
  491. listCompany(query).then((res) => {
  492. cb(res.rows);
  493. });
  494. }
  495. function handleSelectCompany(item) {
  496. form.value.companyName = item.name;
  497. form.value.companyId = item.id;
  498. }
  499. function prevYear() {
  500. let currentYear = queryParams.value.year;
  501. currentYear = Number(currentYear) - 1;
  502. queryParams.value.year = currentYear.toString();
  503. handleQuery();
  504. }
  505. function nextYear() {
  506. let currentYear = queryParams.value.year;
  507. currentYear = Number(currentYear) + 1;
  508. queryParams.value.year = currentYear.toString();
  509. handleQuery();
  510. }
  511. function monthStatusStyle(row, month) {
  512. const index = row.records.findIndex((v) => v.month === month);
  513. if (index >= 0) {
  514. return {
  515. backgroundColor: getStatusColor(row.records[index].status),
  516. verticalAlign: "middle",
  517. width: "14px",
  518. height: "14px",
  519. };
  520. } else {
  521. return {
  522. backgroundColor: getStatusColor(0),
  523. verticalAlign: "middle",
  524. width: "14px",
  525. height: "14px",
  526. };
  527. }
  528. }
  529. function getStatusColor(status) {
  530. const index = selectStatus.value.findIndex((v) => v.value === status);
  531. return index >= 0 ? selectStatus.value[index].color : "#fff";
  532. }
  533. function clearStatus() {
  534. queryParams.value.status = null;
  535. }
  536. function setServiceHandler() {
  537. if (ids.value.length === 0) {
  538. proxy.$modal.msgError("请先选择需要设置的工单!");
  539. return;
  540. }
  541. proxy.$refs["serviceRef"].open({
  542. dialogTitle: "设置执行人",
  543. dialogContent: "请输入执行人姓名",
  544. values: ids.value,
  545. });
  546. }
  547. function getTransactor(row) {
  548. if (row.entrusts != null && row.entrusts.length > 0) {
  549. const names = Array.from(new Set(row.entrusts.map((v) => v.toAccountName)));
  550. return names.join(",");
  551. } else {
  552. return row.serviceName;
  553. }
  554. }
  555. function handleByRow(row, item) {
  556. console.log(row);
  557. const record = row.records.find(
  558. (v) =>
  559. v.fromId === "0" && v.year === queryParams.value.year && v.month === item
  560. );
  561. const editable =
  562. permissions.includes(all_permission) ||
  563. permissions.includes("business:customer:service:loop:edit") >= 0;
  564. const viewable =
  565. permissions.includes(all_permission) ||
  566. permissions.includes("business:customer:service:loop:view") >= 0;
  567. if (record == null && row.isStop == 1) {
  568. proxy.$modal.msg("工单已终止");
  569. return;
  570. }
  571. if (
  572. record != null &&
  573. record.status === 3 &&
  574. (editable || viewable) &&
  575. row.isStop == 1
  576. ) {
  577. if (row.taskTypeId === "1") {
  578. keepAccountViewRef.value.open({
  579. workOrderId: row.id,
  580. month: item,
  581. year: queryParams.value.year,
  582. companyId: row.companyId,
  583. companyName: row.companyName,
  584. });
  585. } else if (row.taskTypeId === "2") {
  586. socialSecurityViewRef.value.open({
  587. workOrderId: row.id,
  588. month: item,
  589. year: queryParams.value.year,
  590. companyId: row.companyId,
  591. companyName: row.companyName,
  592. });
  593. } else if (row.taskTypeId === "3") {
  594. housingFundViewRef.value.open({
  595. workOrderId: row.id,
  596. month: item,
  597. year: queryParams.value.year,
  598. companyId: row.companyId,
  599. companyName: row.companyName,
  600. });
  601. } else if (row.taskTypeId === "4") {
  602. }
  603. } else if (
  604. row.entrusts != null &&
  605. row.entrusts.length > 0 &&
  606. (editable || viewable)
  607. ) {
  608. if (
  609. row.entrusts.findIndex(
  610. (v) =>
  611. proxy.moment(v.currentMonth).format("YYYYMM") ===
  612. queryParams.value.year + item
  613. ) >= 0
  614. ) {
  615. if (row.taskTypeId === "1") {
  616. keepAccountViewRef.value.open({
  617. workOrderId: row.id,
  618. month: item,
  619. year: queryParams.value.year,
  620. companyId: row.companyId,
  621. companyName: row.companyName,
  622. });
  623. } else if (row.taskTypeId === "2") {
  624. socialSecurityViewRef.value.open({
  625. workOrderId: row.id,
  626. month: item,
  627. year: queryParams.value.year,
  628. companyId: row.companyId,
  629. companyName: row.companyName,
  630. });
  631. } else if (row.taskTypeId === "3") {
  632. housingFundViewRef.value.open({
  633. workOrderId: row.id,
  634. month: item,
  635. year: queryParams.value.year,
  636. companyId: row.companyId,
  637. companyName: row.companyName,
  638. });
  639. } else if (row.taskTypeId === "4") {
  640. }
  641. } else if (editable) {
  642. if (row.taskTypeId === "1") {
  643. keepAccountFormRef.value.open({
  644. workOrderId: row.id,
  645. month: item,
  646. year: queryParams.value.year,
  647. companyId: row.companyId,
  648. companyName: row.companyName,
  649. });
  650. } else if (row.taskTypeId === "2") {
  651. socialSecurityFormRef.value.open({
  652. workOrderId: row.id,
  653. month: item,
  654. year: queryParams.value.year,
  655. companyId: row.companyId,
  656. companyName: row.companyName,
  657. });
  658. } else if (row.taskTypeId === "3") {
  659. housingFundFormRef.value.open({
  660. workOrderId: row.id,
  661. month: item,
  662. year: queryParams.value.year,
  663. companyId: row.companyId,
  664. companyName: row.companyName,
  665. });
  666. } else if (row.taskTypeId === "4") {
  667. }
  668. } else {
  669. proxy.$modal.msg("没有编辑权限");
  670. }
  671. } else if (editable) {
  672. if (row.taskTypeId === "1") {
  673. keepAccountFormRef.value.open({
  674. workOrderId: row.id,
  675. month: item,
  676. year: queryParams.value.year,
  677. companyId: row.companyId,
  678. companyName: row.companyName,
  679. });
  680. } else if (row.taskTypeId === "2") {
  681. socialSecurityFormRef.value.open({
  682. workOrderId: row.id,
  683. month: item,
  684. year: queryParams.value.year,
  685. companyId: row.companyId,
  686. companyName: row.companyName,
  687. });
  688. } else if (row.taskTypeId === "3") {
  689. housingFundFormRef.value.open({
  690. workOrderId: row.id,
  691. month: item,
  692. year: queryParams.value.year,
  693. companyId: row.companyId,
  694. companyName: row.companyName,
  695. });
  696. } else if (row.taskTypeId === "4") {
  697. }
  698. } else {
  699. proxy.$modal.msg("没有编辑权限");
  700. }
  701. }
  702. getList();
  703. </script>