detailsAll.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332
  1. <template>
  2. <u-navbar :titleStyle="{ color: '#000' }" :autoBack="true" title="日报详情" :placeholder="true" :safeAreaInsetTop="true" bgColor="#fff">
  3. <template #left>
  4. <view class="u-navbar__content__left__item">
  5. <u-icon name="arrow-left" size="20" color="#000" @click="returnTo('business/common/projectMange/record/index')"></u-icon>
  6. </view>
  7. </template>
  8. </u-navbar>
  9. <oa-scroll
  10. customClass="record-container scroll-height"
  11. :pageSize="pageSize"
  12. :total="total"
  13. :isSticky="true"
  14. :customStyle="{
  15. //#ifdef APP-PLUS || MP-WEIXIN
  16. height: `calc(100vh - 44px)`,
  17. //#endif
  18. //#ifdef H5
  19. height: `calc(100vh - 44px)`,
  20. //#endif
  21. }"
  22. :refresherLoad="true"
  23. :refresherEnabled="true"
  24. :refresherDefaultStyle="'none'"
  25. :refresherThreshold="44"
  26. :lowerThreshold="44"
  27. :refresherBackground="'#f5f6f7'"
  28. @load="load"
  29. @refresh="refresh"
  30. :data-theme="'theme-' + proxy.$settingStore.themeColor.name"
  31. >
  32. <template #default>
  33. <view class="content-area radius bg-white" v-for="(item, index) in dataList" :key="index" style="margin-top: 6px">
  34. <view class="content-area-header flex mb10">
  35. <img :src="item?.avatar" class="content-area-header-avatarImg mr10" v-if="item?.avatar" />
  36. <u-avatar
  37. v-if="!item?.avatar"
  38. class="content-area-header-avatar mr10"
  39. :text="item.createBy.length > 2 ? item.createBy.slice(1, 3) : item.createBy"
  40. shape="square"
  41. size="40"
  42. fontSize="12"
  43. color="#ffffff"
  44. :bgColor="proxy.$settingStore.themeColor.color"
  45. ></u-avatar>
  46. <view>
  47. <view class="content-area-header-title font16 mb5">{{ item.createBy ? item.createBy : " " }} {{ item.submitDate.slice(0, 10) != item.reportDate ? "( " + item.reportDate + " )" : "" }}</view>
  48. <view class="content-area-header-time font14">{{ item.submitDate ? item.submitDate.replace("T", " ") : " " }}</view>
  49. </view>
  50. </view>
  51. <view class="content-area-center mb10" v-for="child in item.workContents" :key="child">
  52. <view class="content-area-center-top flex">
  53. <view class="content-area-center-top-title mr10" style="color: #559aff" @click="toProjectMange(child.projectId)">{{ child.projectName ? child.projectName : " " }}</view>
  54. <view class="content-area-center-top-time" :style="{ color: proxy.$settingStore.themeColor.color }">{{ child.workTime }}h</view>
  55. </view>
  56. <u-text :text="child.workContent" color="#000000" size="14"></u-text>
  57. </view>
  58. <view class="content-area-center mb10">
  59. <view class="content-area-center-top"> 明日计划 </view>
  60. <u-text :text="item.tomorrowPlan ? item.tomorrowPlan : '无'" color="#000000" size="14"></u-text>
  61. </view>
  62. <view class="content-area-center mb10">
  63. <view class="content-area-center-top"> 工作协调 </view>
  64. <u-text :text="item.coordinateWork ? item.coordinateWork : '无'" color="#000000" size="14"></u-text>
  65. </view>
  66. <view class="content-area-center mb10">
  67. <view class="content-area-center-top">图片</view>
  68. <view class="imageBox" v-if="JSON.parse(item.reportImage) && JSON.parse(item.reportImage).length > 0">
  69. <image class="image m5" style="width: 50px" mode="widthFix" v-for="(a, index2) in JSON.parse(item.reportImage)" :key="index2" :src="a.url" @click="previewImage(index,index)" />
  70. </view>
  71. <view class="imageBox" v-else>无</view>
  72. </view>
  73. <view class="content-area-center mb10">
  74. <view class="content-area-center-top">附件 </view>
  75. <view v-if="JSON.parse(item.reportFile) && JSON.parse(item.reportFile).length > 0">
  76. <uni-link v-for="(file, index2) in JSON.parse(item.reportFile)" :key="index2" :href="file.url" text="file.url" style="color: rgba(0, 0, 0, 0.7)">{{ file.name }}</uni-link>
  77. </view>
  78. <view v-else>无</view>
  79. </view>
  80. <view class="content-area-center mb10" style="display: flex; flex-wrap: wrap" v-if="item.pmReportReaders.read > 0 || item.pmReportReaders.unRead > 0">
  81. <u-tabs
  82. :list="item.tabsList"
  83. :current="item.tab"
  84. @click="tabsClick(index, $event.value)"
  85. lineColor="#333"
  86. :activeStyle="{ color: '#333', fontSize: '14px' }"
  87. :inactiveStyle="{ color: '#909399', fontSize: '14px' }"
  88. :scrollable="false"
  89. style="width: 100%"
  90. ></u-tabs>
  91. <view class="content-area-header mt20 mb10 text-center" style="display: inline-block" v-for="(item2, index2) in item.tabsList[item.tab].treeSelectNodes" :key="index2">
  92. <img v-if="item2?.avatar" class="content-area-header-avatarImg mlr5" :src="item2.avatar" style="display: block; width: 40px; height: 40px" />
  93. <u-avatar
  94. v-if="!item2.avatar"
  95. class="content-area-header-avatar mlr5"
  96. :text="item2.nickName.length > 2 ? item2.nickName.slice(1, 3) : item2.nickName"
  97. shape="square"
  98. size="40"
  99. fontSize="12"
  100. color="#ffffff"
  101. :bgColor="proxy.$settingStore.themeColor.color"
  102. ></u-avatar>
  103. <u-text :text="item2.nickName" color="#000000" size="14" align="center"></u-text>
  104. </view>
  105. </view>
  106. </view>
  107. </template>
  108. </oa-scroll>
  109. </template>
  110. <script setup>
  111. /*----------------------------------依赖引入-----------------------------------*/
  112. import { onLoad, onShow, onReady, onHide, onLaunch, onBackPress, onUnload, onNavigationBarButtonTap, onPageScroll } from "@dcloudio/uni-app";
  113. import { ref, reactive, computed, getCurrentInstance, toRefs, inject } from "vue";
  114. /*----------------------------------接口引入-----------------------------------*/
  115. import { projectApi } from "@/api/business/project.js";
  116. import { dUserList } from "@/api/system/user.js";
  117. import { deptUserTreeSelect } from "@/api/system/user.js";
  118. /*----------------------------------组件引入-----------------------------------*/
  119. /*----------------------------------store引入-----------------------------------*/
  120. /*----------------------------------公共方法引入-----------------------------------*/
  121. /*----------------------------------公共变量-----------------------------------*/
  122. const { proxy } = getCurrentInstance();
  123. /*----------------------------------变量声明-----------------------------------*/
  124. const tree = ref({
  125. value: "tree_root",
  126. label: "Root",
  127. children: [],
  128. });
  129. const reportDetailData = ref([]);
  130. const pmReportReaders = ref([]); //已读未读集合
  131. const state = reactive({
  132. loading: true,
  133. dataList: [], //日报列表
  134. options: {
  135. //日报详情参数
  136. reportId: "",
  137. },
  138. userData: [], //用户列表
  139. pageSize:1,
  140. pageNum:0,
  141. total:10,
  142. submitDate:undefined,
  143. });
  144. const { dataList, userData, tabsList, tabsCurrent, pageSize, pageNum, total, } = toRefs(state);
  145. /**
  146. * 返回上级页面
  147. * @param defaultPage 默认页面
  148. */
  149. function returnTo(defaultPage) {
  150. if(getCurrentPages().length > 1){
  151. uni.navigateBack()
  152. }else{
  153. uni.redirectTo({
  154. url: `/pages/${defaultPage}`
  155. })
  156. }
  157. }
  158. /**
  159. * @tabs点击事件
  160. */
  161. function tabsClick(index,e) {
  162. dataList.value[index].tab = e
  163. }
  164. function previewImage(index1,index2) {
  165. uni.previewImage({
  166. current: index2, // 当前显示图片索引
  167. urls: dataList.value[index1].images[index2], // 需要预览的图片http链接列表
  168. });
  169. }
  170. /**
  171. * @初始化
  172. */
  173. function init() {
  174. dataList.value = [];
  175. state.loading = true;
  176. /** 查询树结构用户列表 回显抄送人*/
  177. deptUserTreeSelect({ pageNum: "1", pageSize: "1000" }).then((res) => {
  178. tree.value = res.data;
  179. projectApi()
  180. .ReportRecord({
  181. // pageNum: ++ pageNum.value ,
  182. // pageSize: 1,
  183. // projectAscription:2,
  184. // submitterId:state.options.submitterId,
  185. reportId:state.options.reportId,
  186. pageNum: 1,
  187. pageSize: 1,
  188. })
  189. .then((requset) => {
  190. dataRebuild(requset.data.records);
  191. state.loading = false;
  192. }).catch((err) => {
  193. state.loading = false;
  194. });
  195. });
  196. }
  197. /**
  198. *
  199. * @param item 数据重组
  200. */
  201. function dataRebuild(item,type){
  202. for(let i=0;i<item.length;i++){
  203. item[i].tabsList = [
  204. { name: "已读(" + item[i].pmReportReaders.read + ")", value: 0,
  205. treeSelectNodes:proxy.$common.findTreeNodes(tree.value, item[i].pmReportReaders.readAlready),num:item[i].pmReportReaders.read},
  206. { name: "未读(" + item[i].pmReportReaders.unRead + ")", value: 1,
  207. treeSelectNodes:proxy.$common.findTreeNodes(tree.value,item[i].pmReportReaders.readNotAlready),num:item[i].pmReportReaders.read},
  208. ];
  209. item[i].tab = 0
  210. var imgs = JSON.parse(item[i].reportImage);
  211. var files = JSON.parse(item[i].reportFile);
  212. imgs.forEach(function (val) {
  213. item[i].images.push(val.url);
  214. });
  215. files.forEach(function (val) {
  216. item[i].files.push(val.url);
  217. });
  218. //数据插入
  219. if(type == "refresh"){
  220. dataList.value.unshift(item[i])
  221. }else{
  222. dataList.value.push(item[i])
  223. }
  224. // 未读状态变更
  225. if(item[i].readFlag == "0"){
  226. projectApi()
  227. .ReportRecordReadFlag({ reportId: item[i].id })
  228. .then((res) => {
  229. if (res.status != "SUCCESS") {
  230. proxy.$modal.msgError("读取异常");
  231. }
  232. });
  233. }
  234. }
  235. }
  236. /**
  237. * 跳转项目概览
  238. * @param id 项目id
  239. */
  240. function toProjectMange(id) {
  241. proxy.$tab.navigateTo(`/pages/business/common/projectMange/overview/index?id=${id}`);
  242. }
  243. /**
  244. * @scrollView加载数据
  245. */
  246. function load() {
  247. projectApi().ReportRecord(
  248. {
  249. upOrDown:0,
  250. slideSum:1,
  251. submitDate:dataList.value[dataList.value.length-1].submitDate,
  252. projectAscription:2,
  253. submitterId:dataList.value[0].submitterId,
  254. }
  255. ).then((requset) => {
  256. if(requset?.data?.records.length>0){
  257. dataRebuild(requset.data.records,"load");
  258. }
  259. })
  260. }
  261. /**
  262. * @scrollView刷新数据
  263. */
  264. function refresh() {
  265. projectApi().ReportRecord(
  266. {
  267. upOrDown:1,
  268. slideSum:1,
  269. submitDate:dataList.value[0].submitDate,
  270. projectAscription:2,
  271. submitterId:dataList.value[0].submitterId,
  272. }
  273. ).then((requset) => {
  274. if(requset?.data?.records.length>0){
  275. dataRebuild(requset.data.records,"refresh");
  276. }
  277. })
  278. }
  279. onReady(() => {});
  280. onShow(() => {
  281. //调用系统主题颜色
  282. proxy.$settingStore.systemThemeColor([1]);
  283. });
  284. onLoad((options) => {
  285. state.options.reportId = options?.reportId;
  286. init();
  287. });
  288. </script>
  289. <style lang="scss" scoped>
  290. .content-area {
  291. margin: 0;
  292. padding: 15px 20px;
  293. overflow: hidden;
  294. &-header {
  295. &-avatar {
  296. margin: auto 0;
  297. }
  298. &-avatarImg {
  299. width: 35px;
  300. height: 35px;
  301. border-radius: 4px;
  302. }
  303. &-title {
  304. margin: 0 0 15px 0;
  305. font-weight: 600;
  306. color: #000000;
  307. }
  308. }
  309. &-center {
  310. line-height: 25px;
  311. &-top {
  312. color: #000000;
  313. font-weight: 600;
  314. }
  315. }
  316. }
  317. </style>