km-expert-details.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573
  1. <template>
  2. <a-card>
  3. <div :class="$style.details">
  4. <a-list item-layout="horizontal" :data-source="data">
  5. <a-list-item slot="renderItem" slot-scope="">
  6. <a-list-item-meta>
  7. <div slot="title" :class="$style.user">
  8. <div :class="$style.userName">
  9. {{ kmExpertDetailsInfo.userName }}
  10. <a-button type="primary" @click="goQuestion(kmExpertDetailsInfo.id)">
  11. 向他提问
  12. </a-button>
  13. </div>
  14. <div :class="$style.userInfo">
  15. <a-descriptions :column="1">
  16. <a-descriptions-item label="知识领域">
  17. {{ kmExpertDetailsInfo.domain }}
  18. </a-descriptions-item>
  19. <a-descriptions-item label="职务">
  20. {{ kmExpertDetailsInfo.station }}
  21. </a-descriptions-item>
  22. <a-descriptions-item label="部门">
  23. {{ kmExpertDetailsInfo.departmentName }}
  24. </a-descriptions-item>
  25. <a-descriptions-item label="办公电话">
  26. <span :class="$style.tel">{{ kmExpertDetailsInfo.phoneNumber }}</span>
  27. </a-descriptions-item>
  28. <a-descriptions-item label="电子邮件">
  29. {{ kmExpertDetailsInfo.email }}
  30. </a-descriptions-item>
  31. <a-descriptions-item label="专家简介">
  32. {{ kmExpertDetailsInfo.introduction }}
  33. </a-descriptions-item>
  34. </a-descriptions>
  35. </div>
  36. <div> </div>
  37. </div>
  38. {{ kmExpertDetailsInfo.exportImg }}
  39. <a-avatar
  40. v-if="kmExpertDetailsInfo.exportImg !== null"
  41. slot="avatar"
  42. :size="65"
  43. :class="$style.userImg"
  44. :src="
  45. `api/flow-mobile/v1/task-form-process/download-attachments/${kmExpertDetailsInfo.exportImg}`
  46. | sdResource
  47. "
  48. />
  49. <a-avatar
  50. v-else
  51. slot="avatar"
  52. :class="$style.userImg"
  53. icon="user"
  54. :size="65"
  55. :src="''"
  56. alt="avatar"
  57. />
  58. </a-list-item-meta>
  59. </a-list-item>
  60. </a-list>
  61. <a-tabs default-active-key="1" @change="callback">
  62. <a-tab-pane key="1" :tab="questionNum" :class="$style.tables">
  63. <a-list
  64. v-if="questionAccounts.length > 0"
  65. item-layout="vertical"
  66. size="large"
  67. :pagination="pagination"
  68. :data-source="questionAccounts"
  69. :class="$style.questionList"
  70. >
  71. <a-list-item slot="renderItem" key="item.title" slot-scope="item, index">
  72. <div v-if="item.isShow" slot="extra" :class="$style.btn">
  73. <span>{{ item.answersNumber }}回复</span>
  74. <a-button type="primary" @click="showModal(item.id)">
  75. 写回答
  76. </a-button>
  77. </div>
  78. <a-icon
  79. :class="$style.questionCircle"
  80. type="question-circle"
  81. theme="twoTone"
  82. two-tone-color="#eb2f96"
  83. />
  84. <a-list-item-meta
  85. :class="$style.questionTitle"
  86. :description="item.description"
  87. @click="lookreply(item, index)"
  88. >
  89. </a-list-item-meta>
  90. <p>{{ item.supplementaryNotes }}</p>
  91. <p v-if="item.isShow"
  92. >提问者:<span>{{ questionAccountDetails.account }}</span> 阅读次数:<span
  93. >{{ questionAccountDetails.readTimes }}次</span
  94. ></p
  95. >
  96. <div v-if="item.isShow" :class="$style.reply">
  97. <div>
  98. <a-list
  99. :class="$style.demoLoadmoreList"
  100. :loading="loading"
  101. item-layout="horizontal"
  102. :data-source="replyData"
  103. >
  104. <a-list-item slot="renderItem" slot-scope="items">
  105. <a-list-item-meta :description="items.answersStr">
  106. <a-avatar
  107. slot="avatar"
  108. icon="user"
  109. :src="
  110. `api/mobile/v1/user-manager/userAvatar/${items.creatorAccount}`
  111. | sdResource
  112. "
  113. />
  114. <span slot="title" :class="$style.time"
  115. >{{ items.creatorName }} | 部门:{{ items.createDeptName }}
  116. <i>{{ items.creationTime | sdDateFormat }}</i>
  117. </span>
  118. </a-list-item-meta>
  119. </a-list-item>
  120. </a-list>
  121. </div>
  122. </div>
  123. </a-list-item>
  124. </a-list>
  125. <a-empty v-else />
  126. </a-tab-pane>
  127. <a-tab-pane key="2" :tab="maptotalSize" force-render>
  128. <sd-data-table
  129. v-if="expressionsmap.length !== 0"
  130. ref="dataTable"
  131. data-url="api/xcoa-mobile/v1/kmkmap/kmKmapData-account-expert"
  132. :columns="columns"
  133. :row-key="'account'"
  134. :filter-expressions="expressionsmap"
  135. @rowClick="rowClick"
  136. @dataLoaded="tableMapDataLoaded"
  137. >
  138. <template v-slot:name="text">
  139. <a>{{ text }}</a>
  140. </template>
  141. </sd-data-table>
  142. </a-tab-pane>
  143. <a-tab-pane key="3" :tab="articeNum" force-render>
  144. <sd-data-table
  145. v-if="expressionsKnowledge.length !== 0"
  146. ref="dataTable2"
  147. data-url="api/xcoa-mobile/v1/kmknowledge/knowledge-account-expert"
  148. :columns="columns2"
  149. :row-key="'account'"
  150. :filter-expressions="expressionsKnowledge"
  151. @rowClick="rowClick2"
  152. @dataLoaded="tableDataLoaded"
  153. >
  154. <template v-slot:name="text">
  155. <a>{{ text }}</a>
  156. </template>
  157. </sd-data-table>
  158. </a-tab-pane>
  159. </a-tabs>
  160. </div>
  161. <!-- 回答弹框 -->
  162. <sd-detail-modal
  163. ref="fwDetail"
  164. page-id="expert/kmExpertAnswers/kmExpertAnswers"
  165. :modal-props="{ width: 1000 }"
  166. @saved="fwSaved"
  167. >
  168. <template v-slot="{ model }">
  169. <sd-form-item name="reply">
  170. <a-textarea v-model="model.reply" :rows="4" placeholder="请输入您的问题" allow-clear />
  171. </sd-form-item>
  172. <sd-form-item
  173. name="expertQuestionId"
  174. :hidden="true"
  175. :input-props="{ defaultValue: answers }"
  176. ></sd-form-item>
  177. </template>
  178. </sd-detail-modal>
  179. <!-- 向他提问弹出框 -->
  180. <sd-detail-modal
  181. ref="question"
  182. page-id="expert/kmExpertQuestion/kmExpertQuestion"
  183. :modal-props="{ width: 1000 }"
  184. @saved="questionfwSaved"
  185. >
  186. <template v-slot="{ model }">
  187. <sd-form-item name="description" />
  188. <sd-form-item name="supplementaryNotes">
  189. <a-textarea
  190. v-model="model.supplementaryNotes"
  191. :rows="4"
  192. placeholder="请输入说明"
  193. allow-clear
  194. />
  195. </sd-form-item>
  196. <sd-form-item name="label" :colspan="3">
  197. <template v-slot:read-and-edit="{ editable }">
  198. <km-tag-picker v-model="model.label" :editable="editable" />
  199. </template>
  200. </sd-form-item>
  201. <sd-form-item
  202. name="expertDataId"
  203. :hidden="true"
  204. :input-props="{ defaultValue: quiz }"
  205. ></sd-form-item>
  206. </template>
  207. </sd-detail-modal>
  208. </a-card>
  209. </template>
  210. <script>
  211. import { Modal } from 'ant-design-vue'
  212. import TableColumnTypes from '@/common/services/table-column-types'
  213. import KmKnowledageService from '../km-knowledage-service'
  214. import components from './_import-components/km-expert-details-import'
  215. const data = [{}]
  216. const columns = [
  217. {
  218. title: '序号',
  219. width: '100px',
  220. align: 'center',
  221. customRender: (text, record, index) => `${index + 1}`,
  222. },
  223. {
  224. title: '地图名称',
  225. dataIndex: 'kmapTitle',
  226. sdClickable: true,
  227. scopedSlots: { customRender: 'name' },
  228. },
  229. {
  230. title: '发布者名称',
  231. dataIndex: 'accountName',
  232. },
  233. {
  234. title: '所属分类',
  235. dataIndex: 'category',
  236. },
  237. ]
  238. const columns2 = [
  239. {
  240. title: '序号',
  241. width: '100px',
  242. align: 'center',
  243. customRender: (text, record, index) => `${index + 1}`,
  244. },
  245. {
  246. title: '标题',
  247. dataIndex: 'title',
  248. sdClickable: true,
  249. scopedSlots: { customRender: 'bt' },
  250. },
  251. {
  252. title: '所属分类',
  253. dataIndex: 'category',
  254. },
  255. {
  256. title: '创建时间',
  257. dataIndex: 'creationTime',
  258. sorter: (a, b) => a.creationTime - b.creationTime,
  259. sdRender: TableColumnTypes.dateTime, // 特殊处理的数据类型,时间戳会自动调用sdDateFormat处理
  260. },
  261. {
  262. title: '阅读次数',
  263. dataIndex: 'readTimes',
  264. sorter: (a, b) => a.readTimes - b.readTimes,
  265. width: '120px',
  266. },
  267. {
  268. title: '推荐次数',
  269. dataIndex: 'recommendTimes',
  270. sorter: (a, b) => a.recommendTimes - b.recommendTimes,
  271. width: '120px',
  272. },
  273. {
  274. title: '点评次数',
  275. dataIndex: 'commentTimes',
  276. sorter: (a, b) => a.commentTimes - b.commentTimes,
  277. width: '120px',
  278. },
  279. ]
  280. export default {
  281. name: 'KmExpertDetails',
  282. metaInfo: {
  283. title: '专家库详情',
  284. },
  285. components: {
  286. ...components,
  287. },
  288. props: {
  289. expertId: {
  290. type: Number,
  291. default: undefined,
  292. },
  293. expertUserAccount: {
  294. type: String,
  295. default: '',
  296. },
  297. },
  298. data() {
  299. return {
  300. data,
  301. columns,
  302. columns2,
  303. isReply: false,
  304. visible: false,
  305. kmExpertDetailsInfo: {},
  306. questionAccounts: [],
  307. questionAccountDetails: {},
  308. replyData: [],
  309. answers: null,
  310. questionNum: '',
  311. maptotalSize: '',
  312. articeNum: '',
  313. kMapid: null,
  314. docReadonly: false,
  315. loading: true,
  316. loadingMore: false,
  317. pagination: {
  318. onChange: (page) => {},
  319. pageSize: 5,
  320. },
  321. actions: [
  322. { type: 'star-o', text: '156' },
  323. { type: 'like-o', text: '156' },
  324. { type: 'message', text: '2' },
  325. ],
  326. expressionsmap: [],
  327. expressionsKnowledge: [],
  328. quiz: null,
  329. showAnswer: false,
  330. isShow: false,
  331. }
  332. },
  333. created() {
  334. // 获取专家信息详情
  335. this.querykmExpertDetails()
  336. },
  337. methods: {
  338. // 向他提问
  339. goQuestion(id) {
  340. this.quiz = id
  341. this.$refs.question.show()
  342. },
  343. // 向他提问保存
  344. questionfwSaved() {
  345. Modal.confirm({
  346. title: '向他提问',
  347. content: '已提交',
  348. onOk: () => {
  349. this.$forceUpdate()
  350. // 获取问题列表
  351. this.queryQuestionAccountExpert()
  352. },
  353. })
  354. },
  355. // 详情
  356. querykmExpertDetails() {
  357. const params = {
  358. id: this.expertId,
  359. }
  360. KmKnowledageService.getkmExpertDetails(params).then((res) => {
  361. this.kmExpertDetailsInfo = { ...res.data }
  362. // 获取问题列表
  363. this.queryQuestionAccountExpert()
  364. const selectValue = {
  365. dataType: 'str',
  366. name: 'account',
  367. op: 'eq',
  368. stringValue: this.kmExpertDetailsInfo.account,
  369. }
  370. this.expressionsmap.push(selectValue)
  371. this.expressionsKnowledge.push(selectValue)
  372. })
  373. },
  374. // 获取问题列表
  375. queryQuestionAccountExpert() {
  376. const params = {
  377. maxResults: 10,
  378. startPosition: 0,
  379. orderBy: 'id desc',
  380. expressions: [
  381. {
  382. dataType: 'str',
  383. name: 'expertDataId',
  384. op: 'eq',
  385. stringValue: this.kmExpertDetailsInfo.id,
  386. },
  387. ],
  388. }
  389. KmKnowledageService.getQuestionAccountExpert(params).then((res) => {
  390. this.questionNum = 'TA的爱问知识' + '(' + res.data.totalSize + ')'
  391. if (res.data.data.length > 0) {
  392. this.loading = false
  393. this.questionAccounts = res.data.data.map((item) => {
  394. this.$set(item, 'isShow', false)
  395. return item
  396. })
  397. } else {
  398. this.questionAccounts = []
  399. }
  400. })
  401. },
  402. // 加载更多
  403. onLoadMore() {
  404. this.loadingMore = true
  405. this.queryAnswersAccountPages((res) => {
  406. this.replyData = this.replyData.concat(res.results)
  407. this.loadingMore = false
  408. this.$nextTick(() => {
  409. window.dispatchEvent(new Event('resize'))
  410. })
  411. })
  412. },
  413. // 获取问题详情
  414. queryQuestionAccountDetails(item) {
  415. const params = {
  416. id: item.id,
  417. }
  418. KmKnowledageService.getQuestionAccountDetails(params).then((res) => {
  419. this.questionAccountDetails = res.data
  420. })
  421. },
  422. // 写回答弹框
  423. showModal(id) {
  424. this.answers = id
  425. this.$refs.fwDetail.show()
  426. },
  427. // 展开回答列表
  428. lookreply(item, index) {
  429. if (item.isShow) {
  430. item.isShow = false
  431. this.isShow = item.isShow
  432. return
  433. }
  434. this.queryAnswersAccountPages(item)
  435. this.queryQuestionAccountDetails(item)
  436. },
  437. // 点击问题 回复接口
  438. queryAnswersAccountPages(item) {
  439. const params = {
  440. maxResults: 10,
  441. startPosition: 0,
  442. orderBy: 'id desc',
  443. expressions: [
  444. {
  445. dataType: 'str',
  446. name: 'expertQuestionId',
  447. op: 'eq',
  448. stringValue: item.id,
  449. },
  450. ],
  451. }
  452. KmKnowledageService.getAnswersAccountPages(params).then((res) => {
  453. this.replyData = res.data.data.length > 0 ? res.data.data : []
  454. this.questionAccounts.forEach((i) => {
  455. i.isShow = false
  456. })
  457. item.isShow = true
  458. })
  459. },
  460. // 知识地图详情
  461. rowClick(record, { rowIndex }) {
  462. window.open(`#/km-kmap-pages/${record.id}`, '_blank')
  463. },
  464. // 知识文档详情
  465. rowClick2(record, { rowIndex }) {
  466. setTimeout(() => {
  467. this.$refs.dataTable2.refresh()
  468. }, 5000)
  469. window.open(`#/km-knowledage-view?id=${record.id}&title=${record.title}`, '_blank')
  470. },
  471. callback(key) {},
  472. // 回答保存
  473. fwSaved() {
  474. Modal.success({
  475. title: '已回答',
  476. onOk: () => {
  477. this.$forceUpdate()
  478. const params = {
  479. id: this.answers,
  480. }
  481. this.queryQuestionAccountExpert()
  482. this.queryAnswersAccountPages(params)
  483. },
  484. })
  485. },
  486. tableMapDataLoaded(pagination) {
  487. this.maptotalSize = 'TA的知识地图' + '(' + pagination.total + ')'
  488. },
  489. tableDataLoaded(pagination) {
  490. this.articeNum = 'TA的知识文档' + '(' + pagination.total + ')'
  491. },
  492. },
  493. }
  494. </script>
  495. <style module lang="scss">
  496. @use '@/common/design' as *;
  497. .details {
  498. .user-img {
  499. width: 70px;
  500. height: 70px;
  501. border: 2px solid $primary-color;
  502. }
  503. .user {
  504. margin-left: 10px;
  505. .user-name {
  506. padding: 0 0 15px 0;
  507. border-bottom: 1px solid #efe9e9;
  508. button {
  509. margin-left: 50px;
  510. }
  511. }
  512. .user-info {
  513. margin-top: 15px;
  514. :global(.ant-descriptions-item-label) {
  515. font-weight: 500;
  516. }
  517. .tel {
  518. color: $primary-color;
  519. text-decoration: underline;
  520. }
  521. }
  522. }
  523. .tables {
  524. margin-top: 20px;
  525. }
  526. .question-list {
  527. padding: 0;
  528. margin-top: -30px;
  529. cursor: pointer;
  530. :global(.ant-list-item-meta) {
  531. display: inline-block;
  532. }
  533. .btn {
  534. button {
  535. margin-left: 10px;
  536. }
  537. }
  538. .question-circle {
  539. padding-right: 10px;
  540. }
  541. }
  542. .demo-loadmore-list {
  543. max-height: 350px;
  544. margin-bottom: 10px;
  545. overflow-y: scroll;
  546. :global(.ant-list-item-meta-avatar) {
  547. float: left;
  548. }
  549. .time {
  550. font-size: $font-size-base;
  551. font-weight: normal;
  552. i {
  553. padding-left: 20px;
  554. font-style: normal;
  555. font-weight: normal;
  556. }
  557. }
  558. }
  559. :global(.ant-list-item-meta-description) {
  560. color: $breadcrumb-last-item-color;
  561. }
  562. .reply {
  563. width: 118%;
  564. border-top: 1px solid #efe9e9;
  565. }
  566. }
  567. </style>