upgradeDowngradeRecord.vue 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432
  1. <!-- 模板区域 -->
  2. <template>
  3. <div>
  4. <PageMain class="vh100 flex-1 overflow-hidden flex flex-col">
  5. <el-tabs v-model="activeTab" @tab-click="handleClick">
  6. <el-tab-pane :label="`待审核 (${pendingReview})`" name="0"></el-tab-pane>
  7. <el-tab-pane :label="`审核通过(${isApproved})`" name="1"></el-tab-pane>
  8. <el-tab-pane :label="`审核不通过(${isNotApproved})`" name="2"></el-tab-pane>
  9. <el-tab-pane :label="`待解锁(${toBeUnlocked})`" name="3" ></el-tab-pane>
  10. <el-tab-pane :label="`已解锁(${unlocked})`" name="4" ></el-tab-pane>
  11. </el-tabs>
  12. <SearchForm :fields="fields" :formInline="formInline" :onSearch="findpage" :onReset="resetForm" />
  13. <div class="flex-1 overflow-auto">
  14. <ComplexTable :tableData="tableData" :columns="columns" :showIndex="false" :columnwidth="250"
  15. :showOperation="['0', '3'].includes(activeTab)" :showSelect="false" :pageInfo="pageInfo"
  16. @getList="getList">
  17. <!-- 自定义操作插槽 -->
  18. <template v-slot:operation="scope">
  19. <el-button v-if="scope.operationData.type == '0'" type="primary" link
  20. @click="isOperationPassed(scope.operationData)">通过</el-button>
  21. <el-button v-if="scope.operationData.type == '0'" type="primary" link
  22. @click="denyOperation(scope.operationData)">拒绝</el-button>
  23. <el-button v-if="scope.operationData.type == '1'" type="primary" link
  24. @click="unlockLevel(scope.operationData)">解锁等级</el-button>
  25. </template>
  26. <!-- 自定义插槽 -->
  27. <template #customSlot="{ bodyCell: { scope, column } }">
  28. <template v-if="column.prop == 'conditions'">
  29. <el-popover placement="bottom" :width="250" trigger="click">
  30. <template #default>
  31. <div v-html="scope.row.conditions"></div>
  32. </template>
  33. <template #reference>
  34. <el-button link type="primary">查看规则</el-button>
  35. </template>
  36. </el-popover>
  37. </template>
  38. <template v-if="column.prop == 'rules'">
  39. <el-popover placement="bottom" :width="250" trigger="click">
  40. <template #default>
  41. <div v-html="scope.row.rules"></div>
  42. </template>
  43. <template #reference>
  44. <el-button link type="primary">查看规则</el-button>
  45. </template>
  46. </el-popover>
  47. </template>
  48. </template>
  49. <!-- 自定义表头插槽 -->
  50. <template v-slot:search="scope">
  51. {{ scope.slotData.label }}
  52. </template>
  53. </ComplexTable>
  54. </div>
  55. </PageMain>
  56. <el-dialog :close-on-click-modal="false" v-model="upgradeReviewVisible" title="升级审核" width="400">
  57. <el-form :model="upgradeReviewInfo" label-width="180px" label-position="top">
  58. <el-form-item label="升级前">
  59. <el-input disabled v-model="upgradeReviewInfo.originalLevel" />
  60. </el-form-item>
  61. <el-form-item label="升级后">
  62. <el-input disabled v-model="upgradeReviewInfo.afterChange" />
  63. </el-form-item>
  64. <el-form-item :label="`升级后${upgradeReviewInfo.originalLevel}佣金比例`" v-if="auditCommissionshow">
  65. <el-input v-model="upgradeReviewInfo.auditCommission">
  66. <template #append>%</template>
  67. </el-input>
  68. </el-form-item>
  69. </el-form>
  70. <template #footer>
  71. <div class="dialog-footer">
  72. <el-button class="border-[#0083FF] color-[#0083FF]" plain @click="upgradeReviewVisible = false">取消</el-button>
  73. <el-button type="primary" @click="upgradeReviewsubmit">
  74. 审核通过
  75. </el-button>
  76. </div>
  77. </template>
  78. </el-dialog>
  79. <el-dialog :close-on-click-modal="false" v-model="OperationVisible" title="驳回原因" width="400">
  80. <el-input type="textarea" :rows="3" placeholder="请输入内容" v-model="rejectReason" maxlength="200" show-word-limit>
  81. </el-input>
  82. <template #footer>
  83. <div class="dialog-footer">
  84. <el-button class="border-[#0083FF] color-[#0083FF]" plain @click="OperationVisible = false">取消</el-button>
  85. <el-button type="primary" @click="OperationVisiblesubmit">
  86. 确定
  87. </el-button>
  88. </div>
  89. </template>
  90. </el-dialog>
  91. <el-dialog :close-on-click-modal="false" v-model="unlockLevelVisible" title="解锁等级" width="500">
  92. <el-form :model="unlockLevelInfo" label-width="180px" label-position="top">
  93. <el-form-item label="支付金额">
  94. <el-input v-model="unlockLevelInfo.paymentAmount" readonly>
  95. <template #append>元</template>
  96. </el-input>
  97. </el-form-item>
  98. <el-form-item label="收款凭证">
  99. <el-upload v-model:file-list="fileList" :limit="1" :auto-upload="false" @change="handleChange"
  100. list-type="picture-card">
  101. <el-icon>
  102. <Plus />
  103. </el-icon>
  104. </el-upload>
  105. </el-form-item>
  106. </el-form>
  107. <template #footer>
  108. <div class="dialog-footer">
  109. <el-button class="border-[#0083FF] color-[#0083FF]" plain @click="unlockLevelVisible = false">取消</el-button>
  110. <el-button type="primary" @click="confirmUnlock">
  111. 确定解锁
  112. </el-button>
  113. </div>
  114. </template>
  115. </el-dialog>
  116. </div>
  117. </template>
  118. <!-- 行为区域 -->
  119. <script lang='ts' setup>
  120. import { ref, reactive, onBeforeMount } from 'vue'
  121. import { ElMessage, ElMessageBox } from 'element-plus'
  122. import type { UploadUserFile } from 'element-plus'
  123. import api from '@/api'
  124. // 页面加载时获取机构列表
  125. onBeforeMount(() => {
  126. getGradeOptions();
  127. findpage();
  128. });
  129. interface PageInfo {
  130. pageNum: number;
  131. pageSize: number;
  132. sizes: number[];
  133. total: number;
  134. }
  135. // 机构树相关变量
  136. const id = ref("");//选中的id
  137. const pendingReview = ref(0);//待审核条数
  138. const isApproved = ref(0);//已审核条数
  139. const isNotApproved = ref(0);//审核不通过条数
  140. const toBeUnlocked = ref(0);//待解锁
  141. const unlocked = ref(0);//已解锁
  142. const upgradeReviewVisible = ref(false);//升级审核弹窗是否显示
  143. const OperationVisible = ref(false);//拒绝操作弹窗是否显示
  144. const auditCommissionshow = ref(true);//是否显示佣金比例
  145. const unlockLevelVisible = ref(false);//解锁等级弹窗是否显示
  146. const upgradeType = ref("");//升级类型
  147. const rejectReason = ref("");//拒绝原因
  148. const fileList = ref<UploadUserFile[]>([
  149. ])
  150. const upgradeReviewInfo = reactive({
  151. originalLevel: "",//原等级
  152. afterChange: "",//变更后等级
  153. auditCommission: "",//比例
  154. });//升级审核表单
  155. const unlockLevelInfo = reactive({
  156. paymentAmount: 0,//支付金额
  157. fileId: '',//图片id
  158. recordId: "",//数据id
  159. });
  160. const tableData = ref([
  161. ]);//表格数据
  162. const formInline = reactive({
  163. name: "",//姓名
  164. mobile: "",//手机号
  165. userId: "",//工号
  166. applyTimes: [],//申请时间
  167. auditStatus: '0',
  168. type: '0'
  169. })
  170. const activeTab = ref('0')
  171. const pageInfo = ref({
  172. pageNum: 1,
  173. pageSize: 20,
  174. sizes: [10, 20, 30, 40, 50],
  175. total: 0,
  176. });
  177. const typeOptions = ref([
  178. {
  179. label: '全部',
  180. value: ' '
  181. },
  182. {
  183. label: '升级',
  184. value: '0'
  185. }, {
  186. label: '降级',
  187. value: '1'
  188. },
  189. ])
  190. //表格字段数据
  191. const fields = ref([
  192. { label: "姓名", model: "name", type: "input", placeholder: "请输入姓名" },
  193. {
  194. label: "手机号", model: "mobile", type: "input", placeholder: "请输入手机号"
  195. },
  196. {
  197. label: "工号", model: "userId", type: "input", placeholder: "请输入工号"
  198. },
  199. {
  200. label: "类型", model: "type", type: "select", placeholder: "选择类型", options: typeOptions.value
  201. },
  202. {
  203. label: "申请时间", model: "applyTimes", type: "date", dateType: "daterange", startplaceholder: "开始时间", endplaceholder: "结束时间",
  204. format: "YYYY-MM-DD", valueFormat: "YYYY-MM-DD",
  205. },
  206. ]);
  207. const columns = [
  208. { prop: "name", label: "姓名", },
  209. { prop: "mobile", label: "手机号", width: '200' },
  210. { prop: "userId", label: "工号", width: '200' },
  211. { prop: "deptName", label: "所属机构", width: '200' },
  212. {
  213. prop: "type", label: "类型", width: '200',
  214. formatter: (row: any) => {
  215. if (row.type === '0') {
  216. return '升级';
  217. } else if (row.type === '1') {
  218. return '降级';
  219. } else {
  220. return '未知类型';
  221. }
  222. }
  223. },
  224. {
  225. prop: "originalLevel", label: "原等级", width: '200',
  226. formatter: (row: any) => {
  227. return userGradeList.value?.find((item: any) => item.grade == row.originalLevel)?.gradeName || '未知等级';
  228. }
  229. },
  230. {
  231. prop: "afterChange", label: "变更后等级", width: '200',
  232. formatter: (row: any) => {
  233. return userGradeList.value?.find((item: any) => item.grade == row.afterChange)?.gradeName || '未知等级';
  234. }
  235. },
  236. {
  237. prop: "conditions", label: "升级条件", width: '200', component: "customSlot",
  238. },
  239. { prop: "rules", label: "考核规则", width: '200', component: "customSlot", },
  240. { prop: "rejectReason", label: "驳回原因", width: '200' },
  241. { prop: "createTime", label: "申请时间", width: '200' },
  242. ];
  243. // 通过
  244. const isOperationPassed = (item: any) => {
  245. console.log(item)
  246. if (item.afterChange == item.originalLevel) {
  247. auditCommissionshow.value = false;
  248. }
  249. id.value = item.id;
  250. upgradeType.value = item.upgradeType;
  251. upgradeReviewVisible.value = true;
  252. upgradeReviewInfo.originalLevel = userGradeList.value.find(val => val.grade == item.originalLevel).gradeName;
  253. upgradeReviewInfo.afterChange = userGradeList.value.find(val => val.grade == item.afterChange).gradeName;
  254. }
  255. // 拒绝操作
  256. const denyOperation = (item: any) => {
  257. OperationVisible.value = true;
  258. id.value = item.id;
  259. }
  260. // 解锁等级
  261. const unlockLevel = (item: any) => {
  262. api.partnerApi.unlockLevels(item.originalLevel).then((res: any) => {
  263. if (res.code == '200') {
  264. unlockLevelInfo.recordId = item.id;
  265. // 使用JavaScript原生方法计算
  266. if (item.frozenAmount) {
  267. // 先将数值转换为字符串处理,避免浮点精度问题
  268. const frozenAmount = Number(item.frozenAmount);
  269. const rate = Number(res.data);
  270. // 计算并保留适当的小数位数
  271. unlockLevelInfo.paymentAmount = Number((frozenAmount * rate / 100).toFixed(2));
  272. } else {
  273. unlockLevelInfo.paymentAmount = 0;
  274. }
  275. unlockLevelVisible.value = true;
  276. } else {
  277. ElMessage.error(res.msg)
  278. }
  279. });
  280. }
  281. // 升级审核提交
  282. const upgradeReviewsubmit = () => {
  283. api.partnerApi[upgradeType.value == '1' ? 'liftingRecorddowngradeAudit' : 'liftingRecordaudit']({
  284. id: id.value,
  285. auditStatus: "1",
  286. auditCommission: upgradeReviewInfo.auditCommission,
  287. }).then((res: any) => {
  288. if (res.code == '200') {
  289. ElMessage.success(res.msg)
  290. upgradeReviewVisible.value = false;
  291. findpage();
  292. } else {
  293. ElMessage.error(res.msg)
  294. }
  295. });
  296. }
  297. const OperationVisiblesubmit = () => {
  298. api.partnerApi[upgradeType.value == '1' ? 'liftingRecorddowngradeAudit' : 'liftingRecordaudit']({
  299. id: id.value,
  300. auditStatus: "2",
  301. rejectReason: rejectReason.value,
  302. }).then((res: any) => {
  303. if (res.code == '200') {
  304. ElMessage.success(res.msg)
  305. OperationVisible.value = false;
  306. findpage();
  307. } else {
  308. ElMessage.error(res.msg)
  309. }
  310. });
  311. }
  312. // 解锁等级
  313. const confirmUnlock = () => {
  314. api.partnerApi.confirmUnlocking(unlockLevelInfo).then((res: any) => {
  315. if (res.code == '200') {
  316. ElMessage({
  317. type: 'success',
  318. message: res.msg,
  319. });
  320. unlockLevelVisible.value = false;
  321. findpage();
  322. } else {
  323. ElMessage({
  324. type: 'error',
  325. message: res.msg,
  326. });
  327. }
  328. });
  329. }
  330. // 处理文件上传
  331. const handleChange = (file: any, FileList: any) => {
  332. let files = file.raw
  333. const params = new FormData(); // 声明formData数据类型
  334. params.append("file", files);
  335. api.commonApi.fileUpload(params).then((res: any) => {
  336. if (res.code == '200') {
  337. unlockLevelInfo.fileId = res.data.id;
  338. } else {
  339. ElMessage.error(res.msg)
  340. }
  341. });
  342. };
  343. // 处理点击事件
  344. const handleClick = (tab: any) => {
  345. activeTab.value = tab.props.name;
  346. findpage();
  347. };
  348. //分页事件
  349. function getList(item: PageInfo) {
  350. pageInfo.value.pageNum = item.pageNum;
  351. pageInfo.value.pageSize = item.pageSize;
  352. findpage();
  353. };
  354. const resetForm = () => {
  355. Object.assign(formInline, {
  356. name: "",//姓名
  357. mobile: "",//手机号
  358. userId: "",//工号
  359. type: "",//类型
  360. applyTimes: [],//申请时间
  361. auditStatus: formInline.auditStatus,
  362. })
  363. findpage();
  364. }
  365. //数据查询
  366. function findpage() {
  367. const currentTab = activeTab.value;
  368. let queryAuditStatus = currentTab;
  369. let queryType: string;
  370. if (currentTab === '3' || currentTab === '4') {
  371. queryType = '1';
  372. queryAuditStatus = currentTab === '4' ? '3' : '0';
  373. } else {
  374. queryType = '0';
  375. }
  376. api.partnerApi.liftingRecordQueryPage({ pages: pageInfo.value.pageNum, size: pageInfo.value.pageSize, ...formInline, type: queryType, auditStatus: queryAuditStatus }).then((res: any) => {
  377. if (res.code == '200') {
  378. tableData.value = res.data.records;
  379. pageInfo.value.pageNum = res.data.current;
  380. pageInfo.value.pageSize = res.data.size;
  381. pageInfo.value.total = res.data.total;
  382. const groupArr = res.data.groupCount || [];
  383. // 待审核:auditStatus = 0
  384. pendingReview.value = groupArr.find(item => item.auditStatus === '00')?.count || 0;
  385. // 已审核:auditStatus = 1
  386. isApproved.value = groupArr.find(item => item.auditStatus === '01')?.count || 0;
  387. // 审核不通过:auditStatus = 2
  388. isNotApproved.value = groupArr.find(item => item.auditStatus === '02')?.count || 0;
  389. // 待解锁:
  390. toBeUnlocked.value = groupArr.find(item => item.auditStatus === '10')?.count || 0;
  391. // 已解锁
  392. unlocked.value = groupArr.find(item => item.auditStatus === '13')?.count || 0;
  393. }
  394. }).catch((err) => {
  395. console.error('分页查询失败:', err)
  396. })
  397. }
  398. // 获取人员等级列表
  399. const userGradeList = ref()
  400. const getGradeOptions = () => {
  401. api.partnerApi.queryGradeName().then((res: any) => {
  402. if (res.code === 200) {
  403. userGradeList.value = res.data;
  404. }
  405. })
  406. }
  407. </script>
  408. <!-- 样式区域 -->
  409. <style lang='scss' scoped>
  410. .custom-tree-node {
  411. flex: 1;
  412. display: flex;
  413. align-items: center;
  414. justify-content: space-between;
  415. font-size: 14px;
  416. padding-right: 8px;
  417. }
  418. :deep(.el-dropdown-link) {
  419. cursor: pointer;
  420. color: var(--el-color-primary);
  421. display: flex;
  422. align-items: center;
  423. margin-left: 15px;
  424. }
  425. </style>