index.vue 20 KB

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