Demand.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622
  1. <template>
  2. <div class="demand">
  3. <el-tabs v-model="form.activeName" class="demo-tabs" @tab-click="handleClick">
  4. <el-tab-pane v-for="tab in tabs" :key="tab.name" :label="$t(tab.label)" :name="tab.name">
  5. <div class="demand-list">
  6. <div v-for="(item, index) in list" :key="index" @click.stop="toDetail(item)" class="li">
  7. <div class="flex-center-between">
  8. <div class="flex-align-center">
  9. <div v-if="form.activeName == 1" class="tag"
  10. :class="{ 'tag_red': item.applyStatus == 2 || item.applyStatus == null }">{{
  11. item.applyStatus == 1 ? $t('workflowTrade.demandStatusSignUping') :
  12. $t('workflowTrade.demandStatusEnded') }}</div>
  13. <div class="title">{{ item.title }}</div>
  14. </div>
  15. <div class="price" v-if="item.budgetMin || item.budgetMax">¥{{ item.budgetMin }}-{{ item.budgetMax }}
  16. </div>
  17. </div>
  18. <div class="flex-align-center content" v-if="item.categoryName3">
  19. <div class="flex-align-center">
  20. <!-- <el-button type="primary" size="small" plain>{{ item.categoryName1 }}</el-button> -->
  21. <!-- <el-button type="primary" size="small" plain>{{ item.categoryName2 }}</el-button> -->
  22. <el-button type="primary" size="small" plain>{{ item.categoryName3 }}</el-button>
  23. </div>
  24. <div class="flex-align-center list">
  25. <div class="lis">
  26. <img src="/src/assets/imgs/yuangong.png" alt="">
  27. <div class="">{{ item.questApplyCount || 0 }}{{ $t('common.renbaoming') }}</div>
  28. </div>
  29. <div class="lis">
  30. <img src="/src/assets/imgs/rili.png" alt="">
  31. <div class="">{{ $t('common.signUpDeadline') }}:{{ item.deadline }}</div>
  32. </div>
  33. </div>
  34. </div>
  35. <div class="description">{{ item.requirements }}</div>
  36. <div class="info">
  37. <div class="info-left">
  38. <el-avatar :size="30" :src="item.userAvatar || appStore.avatarDefault" />
  39. <div class="name">{{ item.nickName }}</div>
  40. <div class="date">{{ item.publishTime }} {{ $t('common.publish') }}</div>
  41. </div>
  42. <div class="info-right flex-align-center">
  43. <template v-if="form.activeName === 0">
  44. <div class="btn" @click.stop="changeItem(item, index, 0)">
  45. <img src="/src/assets/imgs/my/jilu@2x.png" alt="">
  46. <div>{{ $t('personalCenter.viewSignUpRecord') }}</div>
  47. </div>
  48. <template v-if="item.applyStatus == 1">
  49. <div class="btn" @click.stop="changeItem(item, index, 1)">
  50. <img src="/src/assets/imgs/my/bianji@2x.png" alt="">
  51. <div>{{ $t('common.edit') }}</div>
  52. </div>
  53. <div class="btn" @click.stop="changeItem(item, index, 2)">
  54. <img src="/src/assets/imgs/my/guanbi@2x.png" alt="">
  55. <div class="red">{{ $t('personalCenter.endActivity') }}</div>
  56. </div>
  57. </template>
  58. <div class="btn" @click.stop="changeItem(item, index, 3)">
  59. <img src="/src/assets/imgs/my/shanchu@2x.png" alt="">
  60. <div class="red">{{ $t('common.delete') }}</div>
  61. </div>
  62. </template>
  63. <div class="btn" v-else @click.stop="changeItem(item, index, 4)">
  64. <img src="/src/assets/imgs/my/quxiao@2x.png" alt="">
  65. <div class="red">{{ $t('personalCenter.cancelSignUp') }}</div>
  66. </div>
  67. </div>
  68. </div>
  69. </div>
  70. </div>
  71. </el-tab-pane>
  72. </el-tabs>
  73. <template v-if="list.length">
  74. <Pagination :total="form.total" :page-size="form.pageSize" :current-page="form.pageNum"
  75. @page-change="handlePageChange" />
  76. </template>
  77. <el-empty v-else :description="$t('common.empty')" />
  78. <el-dialog v-model="dialogVisible" :title="$t('personalCenter.viewSignUpRecord')" width="1138">
  79. <div class="detail">
  80. <div class="detail-top">
  81. <div class="flex-center-between">
  82. <div class="flex-align-center">
  83. <div class="tag" :class="{ 'tag_red': itemData.applyStatus == '2' }">{{ itemData.applyStatus == 1 ?
  84. $t('workflowTrade.demandStatusSignUping')
  85. :
  86. $t('workflowTrade.demandStatusEnded')
  87. }}</div>
  88. <div class="name">{{ itemData.title }}</div>
  89. </div>
  90. <div class="price">¥{{ itemData.budgetMin }}-{{ itemData.budgetMax }}</div>
  91. </div>
  92. <div class="flex-align-center content">
  93. <div class="flex-align-center">
  94. <!-- <el-button type="primary" size="small" plain>一级分类名称</el-button> -->
  95. <el-button type="primary" size="small" plain>{{ itemData.categoryName3 }}</el-button>
  96. </div>
  97. <div class="flex-align-center list">
  98. <div class="lis">
  99. <img src="/src/assets/imgs/yuangong.png" alt="">
  100. <div class="">{{ itemData.questApplyCount || 0 }}{{ $t('common.renbaoming') }}</div>
  101. </div>
  102. <div class="lis">
  103. <img src="/src/assets/imgs/rili.png" alt="">
  104. <div class="">{{ $t('common.signUpDeadline') }}:{{ itemData.deadline }}</div>
  105. </div>
  106. </div>
  107. </div>
  108. <div class="desc">{{ itemData.requirements }}
  109. </div>
  110. <div class="time">{{ itemData.publishTime }} {{ $t('common.publish') }}</div>
  111. </div>
  112. <div class="detail-txt">{{ $t('personalCenter.baomiliang') }}({{ itemData.questApplyCount || 0 }} {{
  113. $t('personalCenter.ren') }})</div>
  114. <div class="detail-list">
  115. <div v-for="(item, index) in recordList" :key="index" class="li" :class="{'success':item.applyStatus == 1,'failure':item.applyStatus == 2}">
  116. <div class="flex-align-center detail-list-left">
  117. <el-avatar :size="20" :src="item.userAvatar" />
  118. <div class="">{{ item.applyUserName }}</div>
  119. <div class="">{{ item.userPhone }}</div>
  120. </div>
  121. <div class="flex_1 flex-between">
  122. <div class="detail-list-number">{{ $t('personalCenter.gongzuoliuliang') }}:{{ item.publishCount }}</div>
  123. <div class="flex-align-center detail-list-right">
  124. <template v-if="item.applyStatus == 0">
  125. <div @click.stop="changeDemand(item, index, 1)" class="lex-align-center btn green">
  126. <img src="/src/assets/imgs/my/dui@2x.png" alt="">
  127. <div class="">{{ $t('common.agree') }}</div>
  128. </div>
  129. <div @click.stop="changeDemand(item, index, 2)" class="lex-align-center btn red">
  130. <img src="/src/assets/imgs/my/quxiao@2x.png" alt="">
  131. <div class="">{{ $t('common.reject') }}</div>
  132. </div>
  133. </template>
  134. <!-- <div @click="changeDemand(item, index, 3)" class="lex-align-center btn blue">
  135. <img src="/src/assets/imgs/my/jilu@2x.png" alt="">
  136. <div class="">{{ $t('common.viewHomepage') }}</div>
  137. </div> -->
  138. </div>
  139. </div>
  140. </div>
  141. </div>
  142. </div>
  143. <template #footer>
  144. <div class="dialog-footer flex-center">
  145. <el-button @click.prevent="dialogVisible = false">{{ $t('common.cancel') }}</el-button>
  146. <el-button type="primary" class="gradient" @click.prevent="dialogVisible = false">
  147. {{ $t('common.confirm') }}
  148. </el-button>
  149. </div>
  150. </template>
  151. </el-dialog>
  152. </div>
  153. </template>
  154. <script lang="ts" setup>
  155. import { ref, onMounted } from 'vue'
  156. import { useAppStore } from '@/pinia/appStore'
  157. import type { TabsPaneContext } from 'element-plus'
  158. import Pagination from '@/components/Pagination.vue'
  159. import { getWorkflowApplyByUserId, userQuestList, appliList, updateQuestStatus, delectQuest, cancelApply, applyUpdateQuestStatus } from '@/api/my.js'
  160. import { useRoute, useRouter } from 'vue-router'
  161. import DGTMessage from '@/utils/message'
  162. import { ElMessageBox } from 'element-plus'
  163. import { useI18n } from 'vue-i18n'
  164. const { t } = useI18n()
  165. const appStore = useAppStore();
  166. const route = useRoute()
  167. const router = useRouter()
  168. const tabs = ref([
  169. { label: 'personalCenter.publishDemandRecord', name: 0 },
  170. { label: 'personalCenter.myDemandRecord', name: 1 }
  171. ])
  172. const dialogVisible = ref(false)
  173. const list = ref([])
  174. const form = ref({
  175. pageNum: 1,
  176. pageSize: 10,
  177. total: 0,
  178. activeName: 0,
  179. orderByColumn: 'create_time',
  180. isAsc: 'desc'
  181. })
  182. const itemData = ref({})
  183. const recordList = ref([])//报名记录
  184. // 同意拒绝
  185. const changeDemand = async (item, index, applyStatus) => {
  186. if (applyStatus == 3) {
  187. } else {
  188. let res = await applyUpdateQuestStatus({
  189. id: item.id,
  190. applyUserId: item.applyUserId,
  191. applyStatus
  192. })
  193. if (res.code === 200) {
  194. DGTMessage.success(`${t('common.success')}`)
  195. // dialogVisible.value = false;
  196. let result = await appliList({ questId: item.questId });
  197. if (result.code === 200) {
  198. recordList.value = result.rows;
  199. }
  200. }
  201. }
  202. }
  203. const changeItem = async (item, index, type) => {
  204. itemData.value = item;
  205. if (type == 0) {
  206. let res = await appliList({ questId: item.questId })
  207. if (res.code === 200) {
  208. recordList.value = res.rows;
  209. dialogVisible.value = true;
  210. }
  211. } else if (type == 1) {
  212. router.push({ path: `/workflow-trade/workflow-trade-add`, query: { id: item.questId } });
  213. } else if (type == 2) {
  214. ElMessageBox.confirm(
  215. t('personalCenter.jieshuxuqiu') + '?',
  216. t('common.warning'),
  217. {
  218. confirmButtonText: t('common.confirm'),
  219. cancelButtonText: t('common.cancel'),
  220. type: 'warning',
  221. }
  222. )
  223. .then(async () => {
  224. let res = await updateQuestStatus({
  225. questId: item.questId
  226. })
  227. if (res.code === 200) {
  228. getList()
  229. DGTMessage.success(`${t('common.success')}`)
  230. }
  231. })
  232. .catch(() => {
  233. })
  234. } else if (type == 3) {
  235. ElMessageBox.confirm(
  236. t('personalCenter.shifoushanchu'),
  237. t('common.warning'),
  238. {
  239. confirmButtonText: t('common.confirm'),
  240. cancelButtonText: t('common.cancel'),
  241. type: 'warning',
  242. }
  243. )
  244. .then(async () => {
  245. let res = await delectQuest(item.questId)
  246. if (res.code === 200) {
  247. getList()
  248. DGTMessage.success(`${t('common.delete')}${t('common.success')}`)
  249. }
  250. })
  251. .catch(() => {
  252. })
  253. } else if (type == 4) {
  254. ElMessageBox.confirm(
  255. t('personalCenter.sfqxbm'),
  256. t('common.warning'),
  257. {
  258. confirmButtonText: t('common.confirm'),
  259. cancelButtonText: t('common.cancel'),
  260. type: 'warning',
  261. }
  262. )
  263. .then(async () => {
  264. let res = await cancelApply(item.id)
  265. if (res.code === 200) {
  266. getList()
  267. DGTMessage.success(`${t('common.cancel')}${t('common.success')}`)
  268. }
  269. })
  270. .catch(() => {
  271. })
  272. }
  273. }
  274. const toDetail = (item) => {
  275. if (item.title) {
  276. router.push({
  277. path: `/workflow-trade/workflow-trade-detail`,
  278. query: {
  279. questId: item.questId,
  280. metaTitle: item.title
  281. }
  282. })
  283. } else {
  284. DGTMessage.warning(t('personalCenter.gxxybsc'))
  285. }
  286. }
  287. const handleClick = (tab: TabsPaneContext) => {
  288. list.value = []
  289. form.value.pageNum = 1;
  290. form.value.activeName = tab.props.name;
  291. getList()
  292. }
  293. // 获取列表
  294. const getList = async () => {
  295. let res = await (form.value.activeName === 0 ? userQuestList(form.value) : getWorkflowApplyByUserId(form.value))
  296. list.value = res.rows || [];
  297. form.value.total = res.total;
  298. }
  299. const handlePageChange = (page) => {
  300. list.value = []
  301. form.value.pageNum = page;
  302. getList()
  303. }
  304. onMounted(() => {
  305. getList()
  306. })
  307. </script>
  308. <style scoped lang="scss">
  309. .demand {
  310. padding-bottom: 20px;
  311. div {
  312. line-height: 1;
  313. }
  314. .demand-list {
  315. .li {
  316. padding: 16px;
  317. cursor: pointer;
  318. margin-bottom: 16px;
  319. background: #F5F7FA;
  320. border-radius: 16px;
  321. &:last-child {
  322. margin-bottom: 0;
  323. }
  324. .title {
  325. font-size: 18px;
  326. font-weight: bold;
  327. color: #333333;
  328. }
  329. .tag {
  330. padding: 0 12px;
  331. line-height: 30px;
  332. color: #FFFFFF;
  333. font-size: 14px;
  334. background: #2D71FF;
  335. border-radius: 4px;
  336. margin-right: 8px;
  337. }
  338. .tag_red {
  339. background: #E43434;
  340. }
  341. .description {
  342. font-size: 16px;
  343. color: #666666;
  344. line-height: 24px;
  345. margin: 8px 0;
  346. }
  347. .info {
  348. display: flex;
  349. justify-content: space-between;
  350. align-items: center;
  351. .info-left {
  352. display: flex;
  353. align-items: center;
  354. .name {
  355. font-size: 16px;
  356. margin: 0 8px;
  357. }
  358. .date {
  359. font-size: 14px;
  360. color: #666666;
  361. }
  362. }
  363. .info-right {
  364. .btn {
  365. height: 32px;
  366. display: flex;
  367. align-items: center;
  368. padding: 0px 16px;
  369. background: #FFFFFF;
  370. border-radius: 4px;
  371. cursor: pointer;
  372. margin-left: 8px;
  373. img {
  374. width: 14px;
  375. height: 14px;
  376. margin-right: 4px;
  377. }
  378. div {
  379. font-size: 14px;
  380. color: #2D71FF;
  381. }
  382. .red {
  383. color: #E43434;
  384. }
  385. }
  386. }
  387. }
  388. .price {
  389. font-size: 24px;
  390. color: #FD5F3C;
  391. }
  392. }
  393. }
  394. }
  395. .content {
  396. margin-top: 8px;
  397. .list {
  398. .lis {
  399. display: flex;
  400. align-items: center;
  401. img {
  402. width: 16px;
  403. height: 16px;
  404. margin-right: 4px;
  405. }
  406. margin-left: 8px;
  407. div {
  408. font-size: 12px;
  409. }
  410. }
  411. }
  412. }
  413. .detail {
  414. padding: 16px;
  415. border-top: 1px solid #EBEEF5;
  416. .detail-top {
  417. padding: 16px;
  418. background: #F5F7FA;
  419. border-radius: 16px;
  420. border: 1px solid #FFFFFF;
  421. .tag {
  422. padding: 0 12px;
  423. line-height: 30px;
  424. font-size: 14px;
  425. color: #FFFFFF;
  426. background: #2D71FF;
  427. border-radius: 4px;
  428. }
  429. .tag_red {
  430. background: #E43434;
  431. }
  432. .name {
  433. font-size: 18px;
  434. font-weight: bold;
  435. color: #333333;
  436. margin-left: 8px;
  437. }
  438. .price {
  439. color: #FD5F3C;
  440. font-size: 24px;
  441. }
  442. .desc {
  443. margin: 8px 0;
  444. line-height: 24px;
  445. font-size: 16px;
  446. color: #666666;
  447. }
  448. .time {
  449. font-size: 14px;
  450. color: #666666;
  451. }
  452. }
  453. .detail-txt {
  454. line-height: 58px;
  455. font-size: 18px;
  456. font-weight: bold;
  457. }
  458. .detail-list {
  459. .li {
  460. display: flex;
  461. padding: 0 16px;
  462. align-items: center;
  463. justify-content: space-between;
  464. margin-bottom: 16px;
  465. height: 64px;
  466. background: #F5F7FA;
  467. border-radius: 8px;
  468. &:last-child {
  469. margin-bottom: 0;
  470. }
  471. .detail-list-left {
  472. width: 40%;
  473. div {
  474. color: #666666;
  475. font-size: 14px;
  476. &:nth-child(2) {
  477. margin: 0 8px;
  478. font-size: 16px;
  479. color: #333333;
  480. }
  481. }
  482. }
  483. .detail-list-number {
  484. font-size: 14px;
  485. color: #333333;
  486. }
  487. .detail-list-right {
  488. .btn {
  489. display: flex;
  490. margin-left: 8px;
  491. align-items: center;
  492. cursor: pointer;
  493. padding: 0px 16px;
  494. height: 32px;
  495. border-radius: 4px;
  496. font-size: 14px;
  497. &:hover {
  498. opacity: 0.7;
  499. }
  500. img {
  501. width: 14px;
  502. height: 14px;
  503. margin-right: 4px;
  504. }
  505. }
  506. .green {
  507. background: #E9F7EF;
  508. div {
  509. color: #1FB362;
  510. }
  511. }
  512. .red {
  513. background: #FCEBEB;
  514. div {
  515. color: #E43434;
  516. }
  517. }
  518. .blue {
  519. background: #EAF0FF;
  520. div {
  521. color: #2D71FF;
  522. }
  523. }
  524. }
  525. }
  526. .success {
  527. background: #E9F7EF;
  528. }
  529. .failure {
  530. background: #FCEBEB;
  531. }
  532. }
  533. }
  534. </style>