ReviewManagement.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514
  1. <template>
  2. <div ref="courseDom" class="main_container">
  3. <div class="page_item end_item">
  4. <div class="page_search">
  5. <div class="search_content">
  6. <div class="conent_left">
  7. <TabSearch
  8. :tabList="viewModeTabList"
  9. tabType="box"
  10. :defaultTabKey="defaultViewMode"
  11. @tabChange="HandleTabChage"
  12. />
  13. <FormSearchGroup :search-list="searchList"
  14. @searchChange="HandleSearchChange"></FormSearchGroup>
  15. </div>
  16. <div class="conent_right">
  17. <el-button class="button_background" @click="OpenQuestionnaireDialog">创建评价</el-button>
  18. </div>
  19. </div>
  20. </div>
  21. <div class="page_jg_20"></div>
  22. <SearchBlock
  23. :searchList="statusSearchList"
  24. @searchChange="HandleSearchChange">
  25. </SearchBlock>
  26. <div class="page_jg_20"></div>
  27. <!-- 视图展示数据 -->
  28. <div v-if="defaultViewMode == 'view' && questionnaireList?.length > 0"
  29. class="questionnaire_list">
  30. <template
  31. v-for="questionnaire in questionnaireList"
  32. :key="questionnaire.id"
  33. >
  34. <QuestionnaireCard
  35. :cardStatusMsg="reviewManageCardStatusMsg"
  36. :cardTypeMsg="reviewManageTaskTypeMsg"
  37. :questionnaire="questionnaire"
  38. cardType="reviewManage"
  39. @switchOnOff="HandleCardSwitchOnOff"
  40. >
  41. <template #default="{row}">
  42. <el-button @click="GoToQuestionnaireReviewDetail(row)" class="button_background">查看详情</el-button>
  43. <el-button
  44. :class="['button_border']"
  45. @click="OpenQuestionnaireDialog(row)"
  46. >编辑</el-button>
  47. <!-- row.status 0 可以删除/修改 1 不可以 删除/修改 -->
  48. <el-button
  49. :class="[!row.status ? 'delete_button_border' : 'is-disabled' ]"
  50. @click="!row.status ? OpenDeleteDialog(row) : '' "
  51. >删除</el-button>
  52. </template>
  53. </QuestionnaireCard>
  54. </template>
  55. </div>
  56. <!-- 列表展示数据 -->
  57. <Table v-else-if="defaultViewMode == 'list'"
  58. :currentPage="currentPage"
  59. :pageSize="pageSize"
  60. :totalNum="totalNum"
  61. :tableData="questionnaireList"
  62. :tableColumns="questionnaireTableColumns"
  63. >
  64. <template #num="{currentIndex}">
  65. {{ currentIndex + pageSize * (currentPage - 1)}}
  66. </template>
  67. <template #evaluationType="{row}">
  68. {{ reviewManageTaskTypeMsg.find(item=>{return item.type === row.evaluationType})?.title }}
  69. </template>
  70. <template #evaluationStatus="{row}">
  71. <TableRowStatus :useStatus="row.evaluationStatus" :statusMsg="reviewManageRowStatusConvert"></TableRowStatus>
  72. </template>
  73. <template #openStatus="{row}">
  74. <span>
  75. <el-switch
  76. :model-value="Boolean(row.openStatus)"
  77. @change="(val)=>HandleCardSwitchOnOff({id:row.id,onOffVal:val})"
  78. style="--el-switch-on-color: #2e64fa; --el-switch-off-color: #bbbbbb"
  79. />
  80. </span>
  81. </template>
  82. <template #operation="{row}">
  83. <div class="table_row_option">
  84. <span @click="GoToQuestionnaireReviewDetail(row)" :class="['option_button_editor']">查看详情</span>
  85. <span
  86. :class="['el_button_editor']"
  87. @click="OpenQuestionnaireDialog(row)"
  88. >编辑</span>
  89. <span
  90. :class="[!row.status ? 'el_button_delete' : 'editor_disable' ]"
  91. @click="!row.status ? OpenDeleteDialog(row) : '' "
  92. >删除</span>
  93. </div>
  94. </template>
  95. </Table>
  96. </div>
  97. <!-- 创建评价弹窗 -->
  98. <FormDialog
  99. width="590px"
  100. :visible="formDialogVisible"
  101. :submitLoading="formSubmitLoading"
  102. :title="formDialogTitle"
  103. :formItemList="formDialogItmList"
  104. :defaultFormData="defaultFormData"
  105. @formItemChange="HandleFormItmChange"
  106. @close="CloseFormDialog"
  107. @confirm="AddQuestionnaireTask">
  108. </FormDialog>
  109. <!-- 删除确认弹窗 -->
  110. <Dialog
  111. :visible="dialogVisible"
  112. :submitLoading="dialogSubmitLoading"
  113. @close="HandleDialogClose"
  114. @confirm="HandleDialogConfirm"
  115. >
  116. <span class="dialog_alert">确定删除 [ <span class="title">{{ currentOperationRow?.evaluationName}}</span> ] 吗</span>
  117. </Dialog>
  118. </div>
  119. </template>
  120. <script lang="ts" setup>
  121. import {onMounted, ref} from 'vue'
  122. import { useRouter } from 'vue-router';
  123. import { ElMessage } from 'element-plus';
  124. import Table from '@/baseComponents/Table.vue';
  125. import TabSearch from '@/baseComponents/TabSearch.vue';
  126. import TableRowStatus from '@/baseComponents/TableRowStatus.vue';
  127. import Dialog from '@/baseComponents/Dialog.vue';
  128. import FormDialog from '@/baseComponents/FormDialog.vue';
  129. import FormSearchGroup from '@/baseComponents/FormSearchGroup.vue';
  130. import SearchBlock from '@/baseComponents/SearchBlock.vue';
  131. import QuestionnaireCard from '@/components/questionnaireCard/QuestionnaireCard.vue';
  132. import {reviewManageRowStatusConvert, reviewManageTaskTypeMsg, reviewManageCardStatusMsg} from '@/components/statusDict'
  133. import {
  134. getGradeListApi,getQuestionnaireTaskListApi,addQuestionnaireTaskListApi,
  135. getSchoolYearListApi,oppenOrCloseQuestionnaireTaskApi,
  136. editQuestionnaireTaskListApi,deleteQuestionnaireTaskApi
  137. } from '@/api/reviewManagement'
  138. import { unioformDateTransform } from '@/utils/dateTransform';
  139. import {searchList, viewModeTabList, statusSearchList} from './searchListConfig'
  140. import { questionnaireTableColumns } from './table';
  141. import { formDialogItmList } from './formDialog'
  142. interface QuestionnaireItm {
  143. id:Number | String,
  144. evaluationName:String, //标题
  145. teacherName:String, //创建人
  146. evaluationStartDatetime:String, //开始时间
  147. evaluationEndDatetime:String, //结束时间
  148. time:String, //开始时间 + 结束时间
  149. evaluationStatus:Number, // 评价状态,1-进行中,2-已结束
  150. cardStatus:Number,
  151. openStatus:Boolean, // 0 关闭 1 开启
  152. evaluationType:Number|String,
  153. evaluationGrade:Array<String>,
  154. status:Boolean,
  155. }
  156. const router = useRouter()
  157. // 1. 视图模式切换
  158. const defaultViewMode = ref('list')
  159. const HandleTabChage = (val)=>{
  160. console.log('当前模式',val)
  161. defaultViewMode.value = val
  162. }
  163. // 2. 查询参数
  164. const searchParams = ref({
  165. evaluationStatus:'',
  166. evaluationName:'',
  167. schoolYear:'',
  168. })
  169. const HandleSearchChange = async (params,key)=>{
  170. // console.log('获取到的查询参数',params)
  171. searchParams.value = {
  172. ...searchParams.value,
  173. ...params
  174. }
  175. await GetQuestionnaireTaskList()
  176. }
  177. // 获取学年列表信息
  178. const GetSchoolYearList = async()=>{
  179. let res = await getSchoolYearListApi()
  180. let schoolYearOpt = []
  181. if(res?.code == 200){
  182. schoolYearOpt = res?.data?.map(item=>{
  183. return {
  184. label:item.schoolYearName,
  185. value:item.schoolYearCode
  186. }
  187. }) || []
  188. }
  189. searchList.value = searchList.value.map(item=>{
  190. if(item.key == 'schoolYear'){
  191. return {
  192. ...item,
  193. options:[{
  194. label:'全部',
  195. value:'all'
  196. },...schoolYearOpt],
  197. defaultValue:'all'
  198. }
  199. }else{
  200. return item
  201. }
  202. })
  203. }
  204. //.3. 问卷列表
  205. const currentPage = ref(1)
  206. const totalNum = ref(0)
  207. const pageSize = ref(20)
  208. const questionnaireList = ref<QuestionnaireItm[]>([]);
  209. // 问卷开关切换
  210. const HandleCardSwitchOnOff = async(params)=>{
  211. console.log('当前传递的参数---params',params)
  212. const {id,onOffVal} = params
  213. let res = await oppenOrCloseQuestionnaireTaskApi(id,onOffVal ? 1 : 0)
  214. if(res?.code == 200){
  215. // 重新查询表列
  216. await GetQuestionnaireTaskList()
  217. }
  218. }
  219. // 、获取问卷任务列表
  220. const GetQuestionnaireTaskList = async ()=>{
  221. console.log('获取到的查询参数',searchParams.value)
  222. let params = {
  223. pageNum:currentPage.value,
  224. pageSize: pageSize.value,
  225. evaluationStatus: searchParams.value.evaluationStatus == 'all' ? '' : searchParams.value.evaluationStatus,
  226. evaluationName: searchParams.value.evaluationName,
  227. schoolYearCode: searchParams.value.schoolYear == 'all' ? '' : searchParams.value.schoolYear,
  228. }
  229. let res = await getQuestionnaireTaskListApi(params)
  230. if(res?.code == 200){
  231. questionnaireList.value = res.data.records.map(item=>{
  232. return {
  233. ...item,
  234. cardStatus:item.evaluationStatus,
  235. title:item.evaluationName,
  236. time:item.evaluationStartDatetime + ' 至 ' + item.evaluationEndDatetime
  237. }
  238. })
  239. }
  240. }
  241. // 跳转问卷评价详情页
  242. const GoToQuestionnaireReviewDetail = (row)=>{
  243. router.push(`/main/reviewManagementDetail/evaluationData?id=${row.id}`)
  244. }
  245. //4. 新增/修改问卷任务
  246. const formDialogTitle = ref('创建评价')
  247. const formSubmitLoading = ref(false)
  248. const formDialogVisible = ref(false)
  249. const defaultFormData = ref({ //表单默认值
  250. evaluationType:0
  251. })
  252. const currentEditRow = ref({}) //当前编辑的行
  253. const currentEditGradeList = ref([]) //当前编辑/新增 弹窗中 的年级列表数据
  254. // 更新form表单的隐藏和展示项
  255. const UpdataFormDialogItmHideList = (hideKeys:string[])=>{
  256. formDialogItmList.value = formDialogItmList.value.map(item=>{
  257. if(hideKeys.includes(item.key)){
  258. return {
  259. ...item,
  260. hidden:true
  261. }
  262. }else{
  263. return {
  264. ...item,
  265. hidden:false
  266. }
  267. }
  268. })
  269. }
  270. // 更新 新增/修改 状态下,评价方式切换 所展示的 不同表单信息
  271. const UpdataEditOrAddFormHideOfDifferReviewType = (id,type)=>{
  272. switch(Number(type)){
  273. case 0:
  274. case 2:{
  275. if(id){
  276. UpdataFormDialogItmHideList(['evaluationGrade'])
  277. }else{
  278. UpdataFormDialogItmHideList([])
  279. }
  280. break
  281. }
  282. case 1:{
  283. defaultFormData.value.evaluationStartDatetime = ''
  284. defaultFormData.value.evaluationEndDatetime = ''
  285. if(id){
  286. UpdataFormDialogItmHideList(['evaluationStartDatetime','evaluationEndDatetime','evaluationGrade'])
  287. }else{
  288. UpdataFormDialogItmHideList(['evaluationStartDatetime','evaluationEndDatetime'])
  289. }
  290. break
  291. }
  292. }
  293. }
  294. // 切换问卷评价表单内容 _需要根据条件清空开始时间和结束时间
  295. // 同时要判断 当前是 新增 还是 修改
  296. const HandleFormItmChange = (params)=>{
  297. const {key,val,formData} = params
  298. if(key == 'evaluationType'){
  299. console.log('当前参数内容',val)
  300. UpdataEditOrAddFormHideOfDifferReviewType(defaultFormData.value?.id, val);
  301. }
  302. }
  303. // 打开创建问卷弹窗
  304. const OpenQuestionnaireDialog = async (row?:any)=>{
  305. formDialogVisible.value = true
  306. if(row.id){
  307. // 修改
  308. defaultFormData.value = row
  309. // 要判断表单的显隐藏
  310. UpdataEditOrAddFormHideOfDifferReviewType(row.id, row.evaluationType);
  311. }else{
  312. // 新增
  313. let gradeListOption = []
  314. let res = await getGradeListApi()
  315. // 赋值年级下拉
  316. if(res?.code == 200){
  317. currentEditGradeList.value = res.data || []
  318. gradeListOption = res.data.map(item=>{
  319. return {
  320. label:item.gradeName,
  321. value:JSON.stringify({
  322. gradeCode:item.gradeCode,
  323. gradeName:item.gradeName,
  324. gradeId:item.gradeId,
  325. })
  326. }
  327. })
  328. formDialogItmList.value = formDialogItmList.value.map(item=>{
  329. if(item.key == 'evaluationGrade'){
  330. return {
  331. ...item,
  332. selectList:gradeListOption
  333. }
  334. }else {
  335. return item
  336. }
  337. })
  338. }
  339. UpdataFormDialogItmHideList([''])
  340. }
  341. }
  342. // 创建问卷 _保存
  343. const AddQuestionnaireTask = async (params?:any)=>{
  344. const {formData,formRef} = params
  345. console.log('表单信息',formData)
  346. formSubmitLoading.value = true
  347. let selectedGradeData = formData.evaluationGrade?.map(item=>{
  348. return JSON.parse(item)
  349. }) || []
  350. let gradeData = currentEditGradeList.value.map(item=>{
  351. let exitAim = selectedGradeData.find(selectItm=>{
  352. return selectItm.gradeId == item.gradeId
  353. })
  354. return {
  355. ...item,
  356. selectStatus: exitAim ? 1 : 0
  357. }
  358. })
  359. let finalPrams = {
  360. evaluationName: formData.evaluationName,
  361. evaluationType: formData.evaluationType,
  362. evaluationStartDatetime: unioformDateTransform(formData.evaluationStartDatetime),
  363. evaluationEndDatetime: unioformDateTransform(formData.evaluationEndDatetime),
  364. gradeData:gradeData
  365. }
  366. let res = undefined
  367. try{
  368. if(formData.id){
  369. // 修改
  370. res = await editQuestionnaireTaskListApi({...finalPrams,id:formData.id})
  371. }else{
  372. res = await addQuestionnaireTaskListApi(finalPrams)
  373. }
  374. }catch{}
  375. if(res?.code == 200){
  376. ElMessage.success(res.msg)
  377. formRef.resetFields()
  378. CloseFormDialog()
  379. await GetQuestionnaireTaskList() // 重查信息
  380. }else{
  381. formSubmitLoading.value = false
  382. }
  383. }
  384. // 关闭问卷弹窗
  385. const CloseFormDialog = ()=>{
  386. defaultFormData.value = {
  387. evaluationType:0
  388. }
  389. currentEditRow.value = {}
  390. formDialogVisible.value = false
  391. formSubmitLoading.value = false
  392. currentEditGradeList.value = []
  393. }
  394. // 5. 删除问卷
  395. const dialogVisible= ref(false)
  396. const dialogSubmitLoading = ref(false)
  397. const currentOperationRow = ref()
  398. // 打开删除弹窗
  399. const OpenDeleteDialog = (row)=>{
  400. dialogVisible.value = true
  401. currentOperationRow.value = row
  402. }
  403. // 关闭删除弹窗
  404. const HandleDialogClose = ()=>{
  405. dialogVisible.value = false
  406. currentOperationRow.value = null
  407. dialogSubmitLoading.value = false
  408. }
  409. // 确认删除操作
  410. const HandleDialogConfirm = async ()=>{
  411. dialogSubmitLoading.value = true
  412. let res = undefined
  413. try{
  414. res = await deleteQuestionnaireTaskApi(currentOperationRow.value.id)
  415. }catch{}
  416. if(res?.code == 200){
  417. ElMessage.success(res?.msg)
  418. HandleDialogClose()
  419. await GetQuestionnaireTaskList()
  420. }else{
  421. dialogSubmitLoading.value = false
  422. }
  423. }
  424. onMounted(async()=>{
  425. await GetSchoolYearList()
  426. await GetQuestionnaireTaskList()
  427. })
  428. </script>
  429. <style lang="scss" scoped>
  430. .conent_left{
  431. display: flex;
  432. gap:20px;
  433. align-items: center;
  434. .simple_filter{
  435. gap:20px
  436. }
  437. }
  438. :deep(.box_tab){
  439. .selected{
  440. &.prefix{
  441. background: #2E64FA;
  442. color: #fff;
  443. border:none
  444. }
  445. }
  446. }
  447. .dialog_alert{
  448. color:#666;
  449. display: flex;
  450. justify-content: center;
  451. align-items: center;
  452. .title{
  453. color: #333;
  454. }
  455. }
  456. </style>