index.vue 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436
  1. <template>
  2. <MainPanel :style="{ '--photoSize': viewStatus ? '88px' : '64px' }">
  3. <template v-slot:header>
  4. <div class="photos-header">
  5. <div class="left">
  6. <ui-icon
  7. class="back-icon"
  8. type="return"
  9. ctrl
  10. style="margin-right: 10px"
  11. @click="back"
  12. />
  13. <span> {{ sceneTitle }} </span>
  14. </div>
  15. </div>
  16. </template>
  17. <div class="info-layout" ref="layoutRef">
  18. <div class="info-top">
  19. <div class="info-top-left" :class="{ full: viewStatus }">
  20. <Scene :view-status="viewStatus">
  21. <template v-slot="{ childPage }">
  22. <ButtonPane
  23. box-shadow
  24. class="back fun-ctrl"
  25. :size="viewStatus ? 64 : 48"
  26. @click="onScale"
  27. v-if="!childPage"
  28. >
  29. <ui-icon :type="viewStatus ? 'screen_c' : 'screen_f'" class="icon" />
  30. </ButtonPane>
  31. </template>
  32. </Scene>
  33. </div>
  34. <div class="info-top-right" :class="{ full: viewStatus }">
  35. <div class="input-item">
  36. <p>事故时间:</p>
  37. <input
  38. id="accidentTime"
  39. type="text"
  40. v-model="sceneInfo.accidentTime"
  41. @input="inputHandler"
  42. />
  43. </div>
  44. <div class="input-item">
  45. <p>天气:</p>
  46. <input
  47. id="weather"
  48. type="text"
  49. v-model="sceneInfo.weather"
  50. @input="inputHandler"
  51. />
  52. </div>
  53. <div class="input-item">
  54. <p>地点:</p>
  55. <input
  56. id="address"
  57. type="text"
  58. v-model="sceneInfo.address"
  59. @input="inputHandler"
  60. />
  61. </div>
  62. <div class="text-item">
  63. <p>事故描述:</p>
  64. <textarea
  65. id="accidentDesc"
  66. class="info-textarea"
  67. v-model="sceneInfo.accidentDesc"
  68. @input="inputHandler"
  69. ></textarea>
  70. </div>
  71. <div class="info-btn">
  72. <div
  73. class="right-btn"
  74. @click="
  75. router.push({
  76. name: writeRouteName.roads,
  77. params: { type: 'table', back: 1 },
  78. })
  79. "
  80. >
  81. 现场绘图({{ sceneSortPhotos.length }})
  82. </div>
  83. <div class="right-btn" @click="router.push('/accidents?back=1')">
  84. 事故照片({{ accodentSortPhotos.length }})
  85. </div>
  86. </div>
  87. </div>
  88. </div>
  89. <div class="info-bottom" :class="{ full: viewStatus }">
  90. <div v-for="(i, index) in list" @click="router.push(`/tables/${i.type}`)">
  91. <ui-icon :type="i.icon"></ui-icon>
  92. <span> {{ i.name }}</span>
  93. </div>
  94. </div>
  95. </div>
  96. </MainPanel>
  97. </template>
  98. <script lang="ts" setup>
  99. import Scene from "./scene.vue";
  100. import MainPanel from "@/components/main-panel/index.vue";
  101. import UiIcon from "@/components/base/components/icon/index.vue";
  102. import { ref, computed, onMounted, onActivated, nextTick } from "vue";
  103. import { back } from "@/store/sync";
  104. import { router, writeRouteName } from "@/router";
  105. import { roadPhotos } from "@/store/roadPhotos";
  106. import ButtonPane from "@/components/button-pane/index.vue";
  107. import { types, accidentPhotos } from "@/store/accidentPhotos";
  108. import { debounce, getQueryString } from "@/utils";
  109. import { tables } from "@/store/tables";
  110. const layoutRef = ref(null);
  111. const accodentSortPhotos = computed(() => {
  112. const photos = [...accidentPhotos.value];
  113. return photos.sort((a, b) => types.indexOf(a.type) - types.indexOf(b.type));
  114. });
  115. const sceneSortPhotos = computed(() => roadPhotos.value);
  116. const sceneTitle = ref(
  117. getQueryString("title") ? decodeURIComponent(getQueryString("title")) : "案件"
  118. );
  119. const sceneInfo = ref({
  120. accidentTime: "",
  121. weather: "",
  122. address: "",
  123. accidentDesc: "",
  124. });
  125. const inputHandler = debounce(() => {
  126. tables.value["sceneInfo"] = sceneInfo.value;
  127. }, 300);
  128. const viewStatus = ref(false);
  129. const onScale = () => {
  130. viewStatus.value = !viewStatus.value;
  131. };
  132. const list = ref([
  133. {
  134. id: 1,
  135. icon: "prospect",
  136. name: "勘查笔录",
  137. type: "explorate",
  138. },
  139. {
  140. id: 2,
  141. icon: "inquiry",
  142. name: "询问笔录",
  143. type: "ask?type=1",
  144. },
  145. {
  146. id: 3,
  147. icon: "question",
  148. name: "讯问笔录",
  149. type: "ask?type=2",
  150. },
  151. {
  152. id: 4,
  153. icon: "accident",
  154. name: "事故认定",
  155. type: "identification",
  156. },
  157. {
  158. id: 5,
  159. icon: "blood",
  160. name: "血样登记表",
  161. type: "extract",
  162. },
  163. {
  164. id: 6,
  165. icon: "items",
  166. name: "遗留物品清单",
  167. type: "legacy",
  168. },
  169. {
  170. id: 7,
  171. icon: "authorization",
  172. name: "授权委托书",
  173. type: "author",
  174. },
  175. {
  176. id: 8,
  177. icon: "law",
  178. name: "法律法规",
  179. type: "law",
  180. },
  181. ]);
  182. onMounted(() => {
  183. var screenHeight = document.body.clientHeight;
  184. layoutRef.value.style.height = screenHeight + "px";
  185. document.body.style.height = screenHeight + "px";
  186. if (tables.value && tables.value["sceneInfo"]) {
  187. sceneInfo.value = tables.value["sceneInfo"];
  188. }
  189. nextTick(() => {
  190. let sceneCanvas = document.querySelector(".scene-canvas");
  191. sceneCanvas.addEventListener("touchstart", () => {
  192. setBlur();
  193. });
  194. });
  195. });
  196. const setBlur = () => {
  197. let domlList = [];
  198. domlList.push(document.getElementById("accidentTime"));
  199. domlList.push(document.getElementById("weather"));
  200. domlList.push(document.getElementById("address"));
  201. domlList.push(document.getElementById("accidentDesc"));
  202. domlList.forEach((item) => {
  203. item.blur();
  204. });
  205. };
  206. onActivated(async () => {
  207. await nextTick();
  208. let full = router.currentRoute.value.query.full;
  209. if (full) {
  210. viewStatus.value = true;
  211. }
  212. });
  213. </script>
  214. <style scoped lang="scss">
  215. .info-layout {
  216. width: 100%;
  217. height: 100%;
  218. // padding-top: 50px;
  219. background: rgba(22, 24, 26, 1);
  220. padding: 70px 20px 20px 20px;
  221. display: flex;
  222. flex-direction: column;
  223. align-items: center;
  224. justify-content: space-between;
  225. // position: fixed;
  226. // top: 0;
  227. // left: 0;
  228. // z-index: 1;
  229. .info-top {
  230. width: 100%;
  231. height: 83%;
  232. display: flex;
  233. align-items: center;
  234. justify-content: space-between;
  235. .info-top-left {
  236. width: 70%;
  237. height: 100%;
  238. position: relative;
  239. overflow: hidden;
  240. transition: all 0.3s;
  241. &.full {
  242. position: fixed;
  243. width: 100%;
  244. height: 100%;
  245. top: 0;
  246. left: 0;
  247. z-index: 1000;
  248. transform-origin: center center;
  249. .fun-ctrl {
  250. .iconfont {
  251. font-size: 24px;
  252. }
  253. }
  254. }
  255. .hide {
  256. display: none !important;
  257. }
  258. .fun-ctrl {
  259. position: absolute;
  260. left: var(--boundMargin);
  261. top: var(--boundMargin);
  262. padding: 0;
  263. width: 48px;
  264. height: 48px;
  265. display: flex;
  266. align-items: center;
  267. justify-content: center;
  268. .iconfont {
  269. font-size: 18px;
  270. }
  271. }
  272. }
  273. .info-top-right {
  274. width: calc(30% - 20px);
  275. height: 100%;
  276. position: relative;
  277. overflow: hidden;
  278. font-size: 16px;
  279. color: rgba(255, 255, 255, 0.8);
  280. display: flex;
  281. flex-direction: column;
  282. justify-content: space-between;
  283. &.full {
  284. width: 0;
  285. }
  286. p {
  287. margin-bottom: 4px;
  288. }
  289. .input-item {
  290. height: 10%;
  291. input {
  292. width: 100%;
  293. padding: 0 8px;
  294. height: 56%;
  295. background: rgba(255, 255, 255, 0.1);
  296. border-radius: 4px 4px 4px 4px;
  297. border: 1px solid rgba(255, 255, 255, 0.5);
  298. color: rgba(255, 255, 255, 0.8);
  299. }
  300. }
  301. .text-item {
  302. width: 100%;
  303. height: 35%;
  304. .info-textarea {
  305. width: 100%;
  306. padding: 8px;
  307. height: 87%;
  308. background: rgba(255, 255, 255, 0.1);
  309. border-radius: 4px 4px 4px 4px;
  310. border: 1px solid rgba(255, 255, 255, 0.5);
  311. color: rgba(255, 255, 255, 0.8);
  312. outline: none;
  313. resize: none;
  314. }
  315. }
  316. .info-btn {
  317. width: 100%;
  318. height: 19.5%;
  319. display: flex;
  320. flex-direction: column;
  321. justify-content: space-between;
  322. .right-btn {
  323. cursor: pointer;
  324. width: 100%;
  325. height: 42.8%;
  326. background: rgba(255, 255, 255, 0.1);
  327. border-radius: 4px 4px 4px 4px;
  328. display: flex;
  329. align-items: center;
  330. justify-content: center;
  331. }
  332. }
  333. }
  334. }
  335. .info-bottom {
  336. width: 100%;
  337. height: 14.49%;
  338. display: flex;
  339. flex-wrap: nowrap;
  340. &.full {
  341. height: 0;
  342. }
  343. > div {
  344. width: 100%;
  345. height: 100%;
  346. margin-right: 20px;
  347. display: flex;
  348. flex-direction: column;
  349. align-items: center;
  350. justify-content: center;
  351. background: #e6e9f0;
  352. font-size: 16px;
  353. border-radius: 4px;
  354. cursor: pointer;
  355. > span {
  356. margin-top: 8px;
  357. }
  358. .iconfont {
  359. font-size: 24px;
  360. }
  361. &:last-of-type {
  362. margin-right: 0;
  363. }
  364. }
  365. }
  366. }
  367. .photos-header {
  368. width: 100%;
  369. display: flex;
  370. justify-content: space-between;
  371. align-items: center;
  372. position: relative;
  373. .center {
  374. position: absolute;
  375. left: 0;
  376. right: 0;
  377. white-space: nowrap;
  378. // pointer-events: none;
  379. height: 100%;
  380. display: flex;
  381. align-items: center;
  382. justify-content: center;
  383. text-align: center;
  384. }
  385. .left,
  386. .right {
  387. z-index: 1;
  388. }
  389. }
  390. .back-icon {
  391. display: inline-flex;
  392. width: 32px;
  393. height: 32px;
  394. background: rgba(255, 255, 255, 0.1);
  395. border-radius: 24px 24px 24px 24px;
  396. align-items: center;
  397. justify-content: center;
  398. }
  399. </style>
  400. <style lang="scss">
  401. #navCube {
  402. // opacity: 0;
  403. z-index: -1;
  404. pointer-events: none;
  405. }
  406. #home {
  407. opacity: 0;
  408. pointer-events: none;
  409. }
  410. .full {
  411. #navCube {
  412. // opacity: 1;
  413. z-index: 1;
  414. pointer-events: auto;
  415. }
  416. #home {
  417. opacity: 1;
  418. pointer-events: auto;
  419. }
  420. }
  421. </style>