userFeedback.vue 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374
  1. <template>
  2. <div>
  3. <div class="score m-4 bg-white">
  4. <a-collapse v-model:activeKey="activeKey" ghost :bordered="false">
  5. <a-collapse-panel key="1" header="硬件产品评分" ghost :bordered="false">
  6. <GrowCard :loading="loading" class="enter-y" :list="score.hardware" />
  7. </a-collapse-panel>
  8. <a-collapse-panel key="2" header="软件产品评分">
  9. <GrowCard :loading="loading" class="enter-y" :list="score.software" />
  10. </a-collapse-panel>
  11. </a-collapse>
  12. <!-- <div class="scoreTitle text-base">硬件产品评分</div>
  13. <div class="scoreList">
  14. <GrowCard :loading="loading" class="enter-y" :list="score.hardware" />
  15. </div>
  16. <div class="scoreTitle text-base">软件产品评分</div>
  17. <div class="scoreList">
  18. <GrowCard :loading="loading" class="enter-y" :list="score.hardware" />
  19. </div> -->
  20. </div>
  21. <BasicTable @register="registerTable" @editEnd="editEnd">
  22. <template #toolbar>
  23. <a-button type="primary" v-if="getCheckPerm('recruit-add')" @click="router.push('/operate/configuration')"> 选项配置 </a-button>
  24. <a-button type="primary" v-if="getCheckPerm('recruit-add')" @click="downTemplate({})"> 导出 </a-button>
  25. </template>
  26. <template #action="{ record }">
  27. <TableAction
  28. stopButtonPropagation
  29. :actions="[
  30. {
  31. label: record.status == 0 ? '处理' : '查看',
  32. //icon: 'ep:edit',
  33. //ifShow: record.state == 0,
  34. onClick: handleEdit.bind(null, record),
  35. },
  36. ]"
  37. />
  38. </template>
  39. </BasicTable>
  40. <addRecruitModal @register="register" @update="reload" />
  41. </div>
  42. </template>
  43. <script lang="ts">
  44. import { defineComponent, h, ref, onMounted, reactive } from 'vue';
  45. import { BasicTable, useTable, TableAction, BasicColumn, FormProps } from '/@/components/Table';
  46. import { Time } from '/@/components/Time';
  47. import {
  48. getAllByTypeId,
  49. getScoreAug,
  50. getfeedbackList,
  51. employNoteIsTop,
  52. NewPublicNews,
  53. employNoteIsPush,
  54. employNoteDelete,
  55. downTemplate,
  56. } from '/@/api/operate';
  57. import { useModal } from '/@/components/Modal';
  58. import GrowCard from './components/GrowCard.vue';
  59. import { Descriptions } from 'ant-design-vue';
  60. import { useI18n } from '/@/hooks/web/useI18n';
  61. import { useMessage } from '/@/hooks/web/useMessage';
  62. import { Switch } from 'ant-design-vue';
  63. import addRecruitModal from './components/config/messgeModal.vue';
  64. import { useRouter } from 'vue-router';
  65. import { usePermissionStore } from '/@/store/modules/permission';
  66. import { Collapse } from 'ant-design-vue';
  67. export default defineComponent({
  68. components: {
  69. BasicTable,
  70. TableAction,
  71. addRecruitModal,
  72. [Descriptions.name]: Descriptions,
  73. [Descriptions.Item.name]: Descriptions.Item,
  74. GrowCard,
  75. [Collapse.name]: Collapse,
  76. [Collapse.Panel.name]: Collapse.Panel,
  77. },
  78. setup() {
  79. const { t } = useI18n();
  80. const { createMessage } = useMessage();
  81. const permissionStore = usePermissionStore();
  82. const { getCheckPerm } = permissionStore;
  83. const [register, { openModal }] = useModal();
  84. const router = useRouter()
  85. const loading = ref(true);
  86. const score = ref({
  87. hardware: [],
  88. software: [],
  89. });
  90. const activeKey = ref([]);
  91. const fileFlow = reactive({
  92. file: null,
  93. });
  94. const columns: BasicColumn[] = [
  95. {
  96. title: '问题描述',
  97. dataIndex: 'problemDesc',
  98. ellipsis: true,
  99. align: 'left',
  100. width: 250,
  101. },
  102. {
  103. title: '硬件产品',
  104. dataIndex: 'hardwareOption',
  105. ellipsis: true,
  106. width: 150,
  107. customRender: ({ record }) => {
  108. return record.hardwareOption?.nameCn;
  109. },
  110. },
  111. {
  112. title: '软件产品',
  113. dataIndex: 'softwareOption',
  114. ellipsis: false,
  115. width: 200,
  116. customRender: ({ record }) => {
  117. return record.softwareOption?.nameCn;
  118. },
  119. },
  120. {
  121. title: '所在行业',
  122. dataIndex: 'industryOption',
  123. width: 150,
  124. customRender: ({ record }) => {
  125. return record.industryOption?.nameCn;
  126. },
  127. },
  128. {
  129. title: '期望解决方案',
  130. dataIndex: 'solution',
  131. width: 150,
  132. },
  133. {
  134. title: '姓名',
  135. dataIndex: 'nickName',
  136. width: 80,
  137. },
  138. {
  139. title: '联系方式',
  140. dataIndex: 'phone',
  141. width: 120,
  142. },
  143. {
  144. title: '国家和地区',
  145. dataIndex: 'address',
  146. width: 120,
  147. },
  148. {
  149. title: '评分',
  150. dataIndex: 'score',
  151. width: 50,
  152. },
  153. {
  154. title: '评分理由',
  155. dataIndex: 'scoreReason',
  156. width: 150,
  157. },
  158. {
  159. title: '反馈时间',
  160. dataIndex: 'createTime',
  161. width: 150,
  162. customRender: ({ record }) => {
  163. return (
  164. record.createTime &&
  165. h(Time, {
  166. value: record.createTime,
  167. mode: 'datetime',
  168. })
  169. );
  170. },
  171. },
  172. {
  173. title: '处理状态',
  174. dataIndex: 'status',
  175. width: 80,
  176. customRender: ({ record }) => {
  177. return record.status == 0 ? '未处理' : '已处理';
  178. },
  179. },
  180. {
  181. title: '处理结果',
  182. dataIndex: 'result',
  183. width: 120,
  184. customRender: ({ record }) => {
  185. return record.result || '-';
  186. },
  187. },
  188. ];
  189. const searchForm: Partial<FormProps> = {
  190. labelWidth: 100,
  191. autoSubmitOnEnter: true,
  192. autoAdvancedLine: 1,
  193. schemas: [
  194. {
  195. field: 'hardwareOptionId',
  196. component: 'ApiSelect',
  197. label: '硬件产品',
  198. itemProps: {
  199. validateTrigger: 'blur',
  200. },
  201. componentProps: {
  202. api: getAllByTypeId,
  203. numberToString: true,
  204. labelField: 'nameCn',
  205. valueField: 'id',
  206. immediate: true,
  207. params: 2,
  208. },
  209. colProps: {
  210. xl: 6,
  211. xxl: 8,
  212. },
  213. },
  214. {
  215. field: 'softwareOptionId',
  216. component: 'ApiSelect',
  217. label: '软件产品',
  218. itemProps: {
  219. validateTrigger: 'blur',
  220. },
  221. componentProps: {
  222. api: getAllByTypeId,
  223. numberToString: true,
  224. labelField: 'nameCn',
  225. valueField: 'id',
  226. immediate: true,
  227. params: 3,
  228. },
  229. colProps: {
  230. xl: 6,
  231. xxl: 8,
  232. },
  233. },
  234. {
  235. field: 'industryOptionId',
  236. component: 'ApiSelect',
  237. label: '所在行业',
  238. itemProps: {
  239. validateTrigger: 'blur',
  240. },
  241. componentProps: {
  242. api: getAllByTypeId,
  243. numberToString: true,
  244. labelField: 'nameCn',
  245. valueField: 'id',
  246. immediate: true,
  247. params: 1,
  248. },
  249. colProps: {
  250. xl: 6,
  251. xxl: 8,
  252. },
  253. },
  254. {
  255. field: 'status',
  256. label: '处理状态',
  257. component: 'Select',
  258. componentProps: {
  259. options: [
  260. { label: '未处理', value: '0' },
  261. { label: '已处理', value: '1' },
  262. ],
  263. },
  264. colProps: {
  265. xl: 8,
  266. xxl: 8,
  267. },
  268. },
  269. ],
  270. };
  271. const [registerTable, { reload }] = useTable({
  272. api: getfeedbackList,
  273. title: '用户反馈列表',
  274. columns: columns,
  275. useSearchForm: true,
  276. formConfig: searchForm,
  277. showTableSetting: true,
  278. showIndexColumn: false,
  279. canResize: false,
  280. rowKey: 'id',
  281. fetchSetting: {
  282. pageField: 'pageNum',
  283. sizeField: 'pageSize',
  284. listField: 'list',
  285. totalField: 'total',
  286. },
  287. actionColumn: {
  288. width: 220,
  289. title: '操作',
  290. dataIndex: 'action',
  291. slots: { customRender: 'action' },
  292. },
  293. canResize: true,
  294. });
  295. onMounted(() => {
  296. getScoreAug().then(res => {
  297. score.value = res
  298. loading.value = false
  299. })
  300. });
  301. async function handleDelete(record: Recordable) {
  302. await employNoteDelete({ id: record.id });
  303. createMessage.success(t('common.optSuccess'));
  304. reload();
  305. }
  306. async function handlePublish(record: Recordable) {
  307. console.log('点击了发布', record);
  308. await NewPublicNews({ id: record.id, isPublic: 1 });
  309. createMessage.success(t('common.optSuccess'));
  310. reload();
  311. }
  312. function handleEdit(record: Recordable) {
  313. openModal(true, record);
  314. }
  315. async function handleWithdraw(record: Recordable) {
  316. await NewPublicNews({ id: record.id, isPublic: 0 });
  317. createMessage.success(t('common.optSuccess'));
  318. reload();
  319. }
  320. function hendleAddNew() {
  321. console.log('新增新闻');
  322. }
  323. async function editEnd({ record, index, key, value }) {
  324. console.log('editEnd', record, index, key, value);
  325. await addOrUpdate(record);
  326. createMessage.success(t('common.optSuccess'));
  327. }
  328. return {
  329. registerTable,
  330. handleDelete,
  331. handleEdit,
  332. handleWithdraw,
  333. handlePublish,
  334. hendleAddNew,
  335. reload,
  336. register,
  337. openModal,
  338. editEnd,
  339. getCheckPerm,
  340. score,
  341. activeKey,
  342. loading,
  343. router,
  344. downTemplate,
  345. };
  346. },
  347. });
  348. </script>
  349. <style lang="less" scoped>
  350. .score {
  351. .scoreTitle {
  352. margin: 10px 0;
  353. }
  354. .scoreList{
  355. // display: flex;
  356. width: 100%;
  357. overflow: auto;
  358. .scoreitem {
  359. // 保障flex下元素宽度不变
  360. flex-grow: 0;
  361. flex-shrink: 0;
  362. padding: 10px 20px 0 20px;
  363. margin-right: 20px;
  364. width: calc(100% / 6 - 20px);
  365. border: 1px solid #444
  366. }
  367. }
  368. ::v-deep .ant-collapse-item{
  369. background: #fff;
  370. border: none;
  371. }
  372. }
  373. </style>