add.vue 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. <template>
  2. <hc-sys class="hc-add-work-order-page" :isNavBar="false">
  3. <uni-section title="请选择您需要反馈的问题类型" type="line" class="mt-0.5">
  4. <view class="p-3 pt-0" v-if="typeData.length > 0">
  5. <uni-segmented-control :current="typeKey" :values="typeData" @clickItem="typeItemChange" />
  6. </view>
  7. <view class="relative px-3">
  8. <uv-checkbox-group v-model="typeCheckbox" placement="column">
  9. <uv-checkbox v-for="item in typeDataBiz[typeKey]?.children" :key="item.dictKey"
  10. :label="item.dictValue" :name="item.dictValue" class="mb-2"/>
  11. </uv-checkbox-group>
  12. </view>
  13. <view class="p-3 pt-1" v-if="isProblemVal">
  14. <uv-alert showIcon type="error" description="请先选择问题类型"/>
  15. </view>
  16. </uni-section>
  17. <uni-section title="建议反馈内容" type="line" class="mt-1">
  18. <view class="p-3 pt-0">
  19. <textarea v-model="opinionContent" class="p-2 text-26 radius w-full h-200" un-border="1 solid gray-3" placeholder="请输入你宝贵的建议,我们将会跟踪解决"/>
  20. <uv-alert class="mt-2" showIcon type="error" description="请先填写建议反馈内容" v-if="isContent"/>
  21. </view>
  22. </uni-section>
  23. <uni-section title="上传图片文件" type="line" class="mt-1">
  24. <view class="p-3 pt-0">
  25. <uv-alert type="warning" description="请上传JPG、PNG格式的图片文件,最多上传3张图片,文件大小不超过30M"/>
  26. <!-- 图片文件上传 -->
  27. <view class="mt-3">
  28. <hc-row :gutter="10">
  29. <hc-col :span="8" class="h-140" v-for="(item, index) in fileList" :key="index">
  30. <view class="hc-flex h-full b-rounded mr-2" un-border="1 solid gray-2" @click="previewImg(index)">
  31. <hc-image :src="item" class="b-rounded"/>
  32. <view class="hc-tr bg-red-5 text-white text-center w-38 h-38 b-rounded-lb-1 b-rounded-tr-1" @click.stop="delFileClick(index)">
  33. <text class="relative cuIcon-close top--2 text-24"/>
  34. </view>
  35. </view>
  36. </hc-col>
  37. <hc-col :span="8" class="h-140" v-if="fileList.length < 3">
  38. <view class="hc-flex-center h-full b-rounded" un-border="2 dashed gray-2" @click="addFileClick">
  39. <text class="i-iconoir-plus text-70 text-gray-4"/>
  40. </view>
  41. </hc-col>
  42. </hc-row>
  43. </view>
  44. <uv-alert class="mt-2" showIcon type="error" description="请先上传图片文件" v-if="isFiles"/>
  45. </view>
  46. </uni-section>
  47. <!--底部操作栏-->
  48. <HcTabbarBlock :height="70"/>
  49. <hc-tabbars class="flex items-center">
  50. <button hover-class="none" class="cu-btn flex-1 bg-blue-5 text-white" @click="saveClick">提交工单</button>
  51. </hc-tabbars>
  52. </hc-sys>
  53. </template>
  54. <script setup>
  55. import {ref,watch} from "vue";
  56. import mainApi from '~api/other/work-order';
  57. import {onLoad} from '@dcloudio/uni-app'
  58. import {errorToast, successToast} from "@/utils/tools";
  59. import {getArrValue, getObjValue, isNullES} from "js-fast-way";
  60. import {useAppStore} from "@/store";
  61. import {chooseImage} from "@/utils/utils";
  62. import {uploadApi2} from "@/httpApi/modules/upload";
  63. //初始变量
  64. const store = useAppStore()
  65. const projectId = ref(store.projectId);
  66. const contractId = ref(store.contractId);
  67. onLoad(() => {
  68. queryDictBizList()
  69. })
  70. //获取字典信息
  71. const typeDataBiz = ref([])
  72. const queryDictBizList = async () => {
  73. const {error, code, data} = await mainApi.queryDictBizList()
  74. if (!error && code === 200) {
  75. let newArr = [], arr = getArrValue(data);
  76. for (let i = 0; i < arr.length; i++) {
  77. newArr.push(arr[i].dictValue)
  78. }
  79. typeKey.value = 0
  80. typeData.value = newArr
  81. typeDataBiz.value = arr
  82. } else {
  83. typeKey.value = 0
  84. typeData.value = []
  85. typeDataBiz.value = []
  86. }
  87. }
  88. //问题类型
  89. const typeKey = ref(0)
  90. const typeData = ref([])
  91. const typeItemChange = ({currentIndex}) => {
  92. typeCheckbox.value = []
  93. typeKey.value = currentIndex
  94. }
  95. //问题类型的checkbox
  96. const typeCheckbox = ref([])
  97. const isProblemVal = ref(false)
  98. watch(typeCheckbox, (val) => {
  99. if (val.length > 0) {
  100. isProblemVal.value = false
  101. }
  102. })
  103. //意见内容
  104. const opinionContent = ref('')
  105. const isContent = ref(false)
  106. watch(opinionContent, (val) => {
  107. if (!isNullES(val)) {
  108. isContent.value = false
  109. }
  110. })
  111. //上传文件的
  112. const fileList = ref([])
  113. const isFiles = ref(false)
  114. watch(() => fileList.value, (val) => {
  115. if (val.length > 0) {
  116. isFiles.value = false
  117. }
  118. }, {deep: true})
  119. //选择文件上传
  120. const addFileClick = async () => {
  121. const tempFiles = await chooseImage(3 - fileList.value.length)
  122. if (tempFiles.length > 0) {
  123. uni.showLoading({title: '上传文件中...', mask: true});
  124. }
  125. for (let i = 0; i < tempFiles.length; i++) {
  126. const {error, msg, data} = await uploadApi2(tempFiles[i].path)
  127. if (!error) {
  128. const { link } = getObjValue(data)
  129. fileList.value.push(link)
  130. } else {
  131. errorToast(msg)
  132. }
  133. }
  134. uni.hideLoading();
  135. }
  136. //删除文件
  137. const delFileClick = (index) => {
  138. fileList.value.splice(index, 1)
  139. }
  140. //预览图片
  141. const previewImg = (index) => {
  142. uni.previewImage({
  143. current: index,
  144. urls: fileList.value,
  145. });
  146. }
  147. //提交反馈
  148. const saveClick = async () => {
  149. const type_data = typeData.value, type_key = typeKey.value, type_check = typeCheckbox.value
  150. let isForm = true
  151. //问题类型
  152. if (type_check.length <= 0) {
  153. isProblemVal.value = true
  154. isForm = false
  155. }
  156. //内容
  157. const content = opinionContent.value
  158. if (isNullES(content)) {
  159. isContent.value = true
  160. isForm = false
  161. }
  162. //文件
  163. const files = fileList.value
  164. if (files.length <= 0) {
  165. isFiles.value = true
  166. isForm = false
  167. }
  168. if (!isForm) return
  169. //处理数据
  170. uni.showLoading({title: '提交工单中...', mask: true});
  171. const problemType = type_data[type_key] + '-' + type_check.join('-')
  172. //发起请求
  173. const {error, code} = await mainApi.saveUserOpinion({
  174. projectId: projectId.value,
  175. contractId: contractId.value,
  176. problemType: problemType,
  177. opinionContent: content,
  178. returnFiles: files
  179. })
  180. uni.hideLoading();
  181. if (!error && code === 200) {
  182. successToast('提交成功')
  183. setTimeout(() => {
  184. uni.navigateBack()
  185. }, 1500)
  186. } else {
  187. errorToast('提交失败,请稍后重试')
  188. }
  189. }
  190. </script>
  191. <style lang="scss" scoped>
  192. page {
  193. background: #EFEFF4;
  194. }
  195. </style>
  196. <style lang="scss">
  197. @import "@/style/work-order/index.scss";
  198. </style>