detail.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495
  1. <template>
  2. <div id="index">
  3. <el-row>
  4. <el-col :span="24" class="main animate__animated animate__backInRight" v-loading="loading">
  5. <div class="w_1200">
  6. <el-col :span="24" class="one">
  7. <el-row :span="24" class="one_1">
  8. <el-col :span="22" class="title">{{ info.name || '暂无标题' }}</el-col>
  9. <el-col :span="2" class="file" @click="toCollection(0)" v-if="info.is_collection">
  10. <el-icon :size="16"><StarFilled /></el-icon>
  11. <span>已收藏</span>
  12. </el-col>
  13. <el-col :span="2" class="file" @click="toCollection(1)" v-else>
  14. <el-icon :size="16"><Star /></el-icon>
  15. <span>收藏</span>
  16. </el-col>
  17. </el-row>
  18. </el-col>
  19. <el-col :span="24" class="two">
  20. <a-descriptions bordered>
  21. <a-descriptions-item label="服务领域">
  22. {{ info.field || '暂无服务领域' }}
  23. </a-descriptions-item>
  24. <a-descriptions-item label="登记时间">
  25. {{ info.time || '暂无登记时间' }}
  26. </a-descriptions-item>
  27. </a-descriptions>
  28. </el-col>
  29. <el-col :span="24" class="thr">
  30. <el-col :span="24" class="thr_1">
  31. <p>单位信息</p>
  32. </el-col>
  33. <el-row :span="24" class="thr_2">
  34. <el-col :span="17" class="left">
  35. <el-col :span="24" class="name">
  36. {{ formatName(userInfo.name) || '暂无单位' }}
  37. </el-col>
  38. <el-col :span="24" class="other">
  39. <span>联系人</span>
  40. {{ formatName(userInfo.name) || '暂无联系人' }}
  41. </el-col>
  42. </el-col>
  43. <el-col :span="4" class="right" v-if="info.status == '1'">
  44. <a-button type="primary" @click="toChat">
  45. <template #icon>
  46. <MessageOutlined />
  47. </template>
  48. 点击在线洽谈
  49. </a-button>
  50. </el-col>
  51. </el-row>
  52. </el-col>
  53. <a-divider />
  54. <el-col :span="24" class="four">
  55. <el-col :span="24" class="four_1">
  56. <p>服务详情</p>
  57. </el-col>
  58. <el-col :span="24" class="four_2">{{ info.brief || '暂无' }}</el-col>
  59. </el-col>
  60. <el-col :span="24" class="four">
  61. <el-col :span="24" class="four_1">
  62. <p>相关推荐</p>
  63. </el-col>
  64. <el-col :span="24" class="four_3">
  65. <a-list :loading="loading" :grid="{ gutter: 16, column: 4 }" :data-source="list">
  66. <template #renderItem="{ item }">
  67. <el-col :span="24" class="list">
  68. <el-col :span="24" class="name textOver">
  69. <el-tooltip effect="dark" :content="item.name" placement="top">
  70. {{ item.name || '暂无名称' }}
  71. </el-tooltip>
  72. </el-col>
  73. <el-col :span="24" class="two_1">
  74. <span>行业领域:</span>{{ getDict(item.field, 'field') }}
  75. </el-col>
  76. <el-col :span="24" class="two_1">
  77. <span>需求地区:</span>{{ getArea(item.area) }}
  78. </el-col>
  79. <el-col :span="24" class="two_1">
  80. <span>单位:</span> {{ formatName(item.userName) || '暂无单位' }}
  81. </el-col>
  82. <el-col :span="24" class="bottom">
  83. <a-button size="small" type="primary" @click="toView(item)">
  84. 查看详情
  85. </a-button>
  86. </el-col>
  87. </el-col>
  88. </template>
  89. </a-list>
  90. <el-col :span="24" class="page">
  91. <el-pagination
  92. background
  93. layout="total, prev, pager, next"
  94. :page-sizes="[10, 20, 50, 100, 200]"
  95. :total="total"
  96. :page-size="limit"
  97. v-model:current-page="currentPage"
  98. @current-change="changePage"
  99. @size-change="sizeChange"
  100. >
  101. </el-pagination>
  102. </el-col>
  103. </el-col>
  104. </el-col>
  105. </div>
  106. </el-col>
  107. </el-row>
  108. </div>
  109. </template>
  110. <script setup>
  111. import moment from 'moment'
  112. // 基础
  113. import { MessageOutlined } from '@ant-design/icons-vue'
  114. import { get } from 'lodash-es'
  115. const $checkRes = inject('$checkRes')
  116. // 接口
  117. import { DemandStore } from '@/store/api/platform/demand'
  118. import { CollectionStore } from '@/store/api/platform/collection'
  119. import { DictDataStore } from '@/store/api/system/dictData'
  120. const store = DemandStore()
  121. const dictDataStore = DictDataStore()
  122. const collectionStore = CollectionStore()
  123. import { UserStore } from '@/store/user'
  124. const userStore = UserStore()
  125. const user = computed(() => userStore.user)
  126. // 路由
  127. const route = useRoute()
  128. const router = useRouter()
  129. // 加载中
  130. const loading = ref(false)
  131. const info = ref({
  132. key: '1',
  133. name: '长春市XXX有限公司',
  134. field: '科技金融',
  135. time: '2020-07-01'
  136. })
  137. const userInfo = ref({})
  138. // 字典表
  139. const methodList = ref([])
  140. const urgentList = ref([])
  141. const fieldList = ref([])
  142. const demandList = ref([])
  143. // 成果列表
  144. const list = ref([])
  145. let skip = 0
  146. let limit = inject('limit')
  147. const total = ref(0)
  148. // 请求
  149. onMounted(async () => {
  150. loading.value = true
  151. await searchOther()
  152. await search()
  153. await searchAchieve({ skip, limit })
  154. loading.value = false
  155. })
  156. const search = async () => {
  157. let id = route.query.id
  158. if (id) {
  159. // let res = await store.detail(id)
  160. // if (res.errcode == '0') {
  161. // info.value = res.data
  162. // userInfo.value = res.data.userInfo
  163. // }
  164. }
  165. }
  166. const searchAchieve = async (query = { skip: 0, limit }) => {
  167. const info = {
  168. skip: query.skip,
  169. limit: query.limit,
  170. is_use: '0',
  171. status: '1'
  172. }
  173. const res = await store.list(info)
  174. if (res.errcode == '0') {
  175. list.value = res.data
  176. total.value = res.total
  177. }
  178. }
  179. const searchOther = async () => {
  180. // let result
  181. // // 合作方式
  182. // result = await dictDataStore.query({ code: 'method', is_use: '0' })
  183. // if ($checkRes(result)) methodList.value = result.data
  184. // // 需求紧急度
  185. // result = await dictDataStore.query({ code: 'urgent', is_use: '0' })
  186. // if ($checkRes(result)) urgentList.value = result.data
  187. // // 技术领域
  188. // result = await dictDataStore.query({ code: 'field', is_use: '0' })
  189. // if ($checkRes(result)) fieldList.value = result.data
  190. }
  191. // 字典数据转换
  192. const getDict = (data, model) => {
  193. let res
  194. if (model == 'method') res = methodList.value.find((f) => f.value == data)
  195. else if (model == 'urgent') res = urgentList.value.find((f) => f.value == data)
  196. else if (model == 'field') res = fieldList.value.find((f) => f.value == data)
  197. else if (model == 'demand') res = demandList.value.find((f) => f.value == data)
  198. return get(res, 'label')
  199. }
  200. // 时间
  201. const getTime = (data) => {
  202. if (data) return `${data[0]} 至 ${data[1]}`
  203. }
  204. // 地区
  205. const getArea = (data) => {
  206. if (data) return data.join(',')
  207. else return '暂无地区'
  208. }
  209. // 在线洽谈
  210. const toChat = () => {
  211. router.push({ path: '/chat', query: { id: info.value.user } })
  212. }
  213. // 我要对接
  214. const toDocking = () => {
  215. console.log('我要对接')
  216. }
  217. // 收藏
  218. const toCollection = async (status) => {
  219. if (user.value.id) {
  220. let res
  221. let message
  222. const data = {
  223. user: user.value.id,
  224. source: info.value._id,
  225. type: 'demand',
  226. time: moment().format('YYYY-MM-DD')
  227. }
  228. if (status == '1') {
  229. message = '收藏成功'
  230. res = await collectionStore.create(data)
  231. } else {
  232. message = '取消收藏成功'
  233. res = await collectionStore.cancel(data)
  234. }
  235. if (res.errcode === 0) {
  236. ElMessage({
  237. message,
  238. type: 'success'
  239. })
  240. await search()
  241. }
  242. } else {
  243. ElMessage({
  244. message: '未登录无法进行收藏 请登录',
  245. type: 'warning'
  246. })
  247. }
  248. }
  249. // 查看
  250. const toView = (item) => {
  251. router.push({ path: '/demand/detail', query: { id: item.id || item._id } })
  252. }
  253. const formatName = (str) => {
  254. if (str) return str.substr(0, 1) + new Array(str.length).join('*')
  255. }
  256. const currentPage = ref(1)
  257. // 分页
  258. const changePage = (page = currentPage.value) => {
  259. searchAchieve({ skip: (page - 1) * limit, limit: limit })
  260. }
  261. const sizeChange = (limits) => {
  262. console.log(limits)
  263. limit = limits
  264. currentPage.value = 1
  265. searchAchieve({ skip: 0, limit: limit })
  266. }
  267. </script>
  268. <style scoped lang="scss">
  269. .main {
  270. .one {
  271. margin: 10px 0 0 0;
  272. background: #f7f7f7;
  273. padding: 24px;
  274. border-top: 6px solid #2374ff;
  275. overflow: hidden;
  276. border-radius: 0 0 5px 5px;
  277. .one_1 {
  278. margin: 0 0 10px 0;
  279. .title {
  280. font-size: $global-font-size-20;
  281. font-weight: 700;
  282. color: #383b40;
  283. }
  284. .file {
  285. display: flex;
  286. align-items: center;
  287. justify-content: flex-end;
  288. font-family: PingFangSC-Regular;
  289. font-size: $global-font-size-18;
  290. color: #2374ff;
  291. text-align: right;
  292. span {
  293. margin: 0 0 0 5px;
  294. }
  295. }
  296. }
  297. .one_2 {
  298. display: inline-block;
  299. font-size: $global-font-size-14;
  300. background: rgba(18, 172, 117, 0.05);
  301. color: #12ac75;
  302. padding: 0 15px;
  303. height: 20px;
  304. line-height: $global-font-size-20;
  305. border-radius: 10px;
  306. margin-bottom: 2px;
  307. }
  308. }
  309. .two {
  310. background: #f9fafb;
  311. border-radius: 2px;
  312. padding: 30px;
  313. margin: 34px 0 20px;
  314. font-family: PingFangSC-Medium;
  315. font-size: $global-font-size-18;
  316. color: #383b40;
  317. line-height: $global-font-size-16;
  318. }
  319. .thr {
  320. margin: 0 0 10px 0;
  321. .thr_1 {
  322. width: 100%;
  323. height: 40px;
  324. line-height: 40px;
  325. border-bottom: 2px solid #2374ff;
  326. margin: 20px 0;
  327. background: #f7f7f7;
  328. p {
  329. float: left;
  330. padding: 0 20px;
  331. height: 40px;
  332. border-bottom: 2px solid #2374ff;
  333. color: #fff;
  334. font-size: $global-font-size-20;
  335. background: #2374ff;
  336. }
  337. }
  338. .thr_2 {
  339. display: flex;
  340. justify-content: space-between;
  341. align-items: center;
  342. background: #fff;
  343. border: 1px solid #edeff2;
  344. box-shadow: 0 4px 10px 0 rgba(0, 0, 0, 0.03);
  345. border-radius: 2px;
  346. padding: 30px 20px;
  347. .left {
  348. .name {
  349. height: 20px;
  350. font-family: PingFangSC-Semibold;
  351. font-size: $global-font-size-20;
  352. color: #383b40;
  353. line-height: $global-font-size-20;
  354. font-weight: 700;
  355. margin-bottom: 8px;
  356. }
  357. .other {
  358. height: 14px;
  359. font-family: PingFangSC-Medium;
  360. font-size: $global-font-size-18;
  361. color: #383b40;
  362. line-height: $global-font-size-16;
  363. font-weight: 700;
  364. span {
  365. height: 14px;
  366. font-family: PingFangSC-Regular;
  367. font-size: $global-font-size-18;
  368. color: #7e8288;
  369. line-height: $global-font-size-16;
  370. font-weight: 400;
  371. margin-right: 10px;
  372. }
  373. }
  374. }
  375. .right {
  376. display: flex;
  377. justify-content: space-between;
  378. }
  379. }
  380. }
  381. .four {
  382. margin: 0 0 10px 0;
  383. .four_1 {
  384. width: 100%;
  385. height: 40px;
  386. line-height: 40px;
  387. border-bottom: 2px solid #2374ff;
  388. margin: 20px 0;
  389. background: #f7f7f7;
  390. p {
  391. float: left;
  392. padding: 0 20px;
  393. height: 40px;
  394. border-bottom: 2px solid #2374ff;
  395. color: #fff;
  396. font-size: $global-font-size-20;
  397. background: #2374ff;
  398. }
  399. }
  400. .four_3 {
  401. margin: 20px;
  402. .list {
  403. border: 1px solid #edeff2;
  404. background: #fff;
  405. box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.03);
  406. border-radius: 2px;
  407. width: 280px;
  408. height: 190px;
  409. margin-bottom: 15px;
  410. cursor: pointer;
  411. transition: all 0.3s;
  412. padding: 15px;
  413. .name {
  414. font-size: $global-font-size-18;
  415. color: #121834;
  416. line-height: $global-font-size-18;
  417. font-weight: 500;
  418. margin: 10px 0;
  419. }
  420. .name:hover {
  421. color: #2374ff;
  422. }
  423. .two_1 {
  424. font-size: $global-font-size-14;
  425. text-align: justify;
  426. line-height: $global-font-size-14;
  427. font-weight: 400;
  428. letter-spacing: 0;
  429. color: #8f97a3;
  430. margin-top: 15px;
  431. span:last-child {
  432. color: #525a68;
  433. }
  434. }
  435. .bottom {
  436. margin: 10px 0 0 0;
  437. text-align: right;
  438. }
  439. }
  440. .list:hover {
  441. background: #f0f7ff;
  442. box-shadow: 0 0 16px rgba(205, 205, 205, 0.6);
  443. }
  444. .page {
  445. display: flex;
  446. flex-direction: row-reverse;
  447. padding: 20px;
  448. }
  449. }
  450. }
  451. .pointer {
  452. display: flex;
  453. align-items: center;
  454. justify-content: flex-end;
  455. font-family: PingFangSC-Regular;
  456. font-size: $global-font-size-18;
  457. color: #7e8288;
  458. margin: 10px 0 0 0;
  459. .money {
  460. margin: 0 10px 0 0;
  461. span {
  462. font-family: PingFangSC-Semibold;
  463. font-size: $global-font-size-22;
  464. color: #e94643;
  465. line-height: $global-font-size-22;
  466. }
  467. }
  468. }
  469. }
  470. </style>