index.vue 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420
  1. <template>
  2. <u-sticky class="shadow-default" bgColor="#fff" style="top: 0">
  3. <u-navbar :titleStyle="{ color: '#000' }" :autoBack="true" title="会议预约" :placeholder="true" :safeAreaInsetTop="true" bgColor="#fff">
  4. <template #left>
  5. <view class="u-navbar__content__left__item">
  6. <u-icon name="arrow-left" size="20" color="#000"></u-icon>
  7. </view>
  8. </template>
  9. <template #right>
  10. <view class="u-navbar__content__right__item">
  11. <u-icon name="more-dot-fill" size="19" color="#000" @click="handleSheet(true, 'rightMore')"></u-icon>
  12. </view>
  13. </template>
  14. </u-navbar>
  15. <view class="flex plr10">
  16. <u--input
  17. style="width: 100%"
  18. v-model="form.meetingRoomName"
  19. placeholder="搜索会议室"
  20. prefixIcon="search"
  21. prefixIconStyle="font-size: 22px;color: #909399"
  22. customStyle="height:35px;background-color:#f5f6fa; "
  23. @confirm="init()"
  24. clearable
  25. ></u--input>
  26. </view>
  27. <switchSlot
  28. :form="form"
  29. :form-data="formData"
  30. :activeColor="proxy.$settingStore.themeColor.color"
  31. disabledColor="#999999"
  32. @changeSheet="1"
  33. @reset="resetSwitch()"
  34. @handleInit="init()"
  35. ></switchSlot>
  36. </u-sticky>
  37. <oa-scroll
  38. customClass="record-container scroll-height"
  39. :isSticky="true"
  40. :customStyle="{
  41. //#ifdef APP-PLUS || MP-WEIXIN
  42. height: `calc(100vh - (44px + 35px + 50px + ${proxy.$settingStore.StatusBarHeight}))`,
  43. //#endif
  44. //#ifdef H5
  45. height: 'calc(100vh - (44px + 35px + 50px))',
  46. //#endif
  47. }"
  48. :pageSize="pageSize"
  49. :total="total"
  50. :refresherLoad="false"
  51. :refresherEnabled="true"
  52. :refresherDefaultStyle="'none'"
  53. :refresherThreshold="44"
  54. :refresherBackground="'#f5f6f7'"
  55. @refresh="refresh"
  56. :data-theme="'theme-' + proxy.$settingStore.themeColor.name"
  57. >
  58. <template #default>
  59. <u-loading-page :loading="state.loading" fontSize="16" style="z-index: 99"></u-loading-page>
  60. <view class="content-area bg-white radius flex flex-wrap m10 p10" v-for="room in dataList" :key="room" @click="handlePopup(true, 'aboutMeeting', room)">
  61. <view class="mr10 mtb-auto">
  62. <u-image v-if="room.imgPath" :show-loading="true" :src="room.imgPath" width="50px" height="50px" radius="5px"></u-image>
  63. <u-image v-else :show-loading="true" src="@/static/images/defaultImg.jpg" width="50px" height="50px" radius="5px"></u-image>
  64. </view>
  65. <view class="mtb-auto">
  66. <view class="font16 text-black mb5">{{ room.roomName }}</view>
  67. <view class="font12 text-gray">可容纳{{ room.capacity || 0 }}人</view>
  68. </view>
  69. <view class="mt10" style="width: 100%">
  70. <timeSlot :currentDay="form.date" :aboutTimeData="room.dmMeetingList" :activeColor="proxy.$settingStore.themeColor.color" />
  71. </view>
  72. </view>
  73. </template>
  74. </oa-scroll>
  75. <u-popup :show="popup.show" mode="bottom" bgColor="#fff" :round="10" @close="popup.show = false">
  76. <view
  77. :style="{
  78. borderTopLeftRadius: '10px',
  79. borderTopRightRadius: '10px',
  80. overflow: 'hidden',
  81. }"
  82. >
  83. <view v-if="popup.type === 'aboutMeeting'">
  84. <view class="flex p15 font16">
  85. <view class="mtb-auto"> {{ popup.list.roomName }}</view>
  86. <view class="mtb-auto ml-auto" @click="handleSheet(true, 'popupMore')">
  87. <u-icon name="info-circle" size="16" label="更多" labelSize="14" labelColor="#333" color="#333"></u-icon>
  88. </view>
  89. </view>
  90. <u-gap height="10" bgColor="#f5f6f7"></u-gap>
  91. <scroll-view scroll-y="true" :scroll-into-view="scrollIntoView" style="height: 42vh">
  92. <u-checkbox-group v-model="checkboxValue" placement="column" shape="circle" :borderBottom="true" @change="checkboxChange">
  93. <view :id="'item' + item.id" v-for="(item, index) in checkboxList" :key="index">
  94. <u-checkbox
  95. :customStyle="{ padding: '15px', margin: '0', backgroundColor: `${item.isDisabledColor}30` }"
  96. :label="item.timeSlot"
  97. :name="item.startTime"
  98. :disabled="item.isDisabled || item.isAbout === '已预约'"
  99. :activeColor="proxy.$settingStore.themeColor.color"
  100. >
  101. <template #label>
  102. <view class="font15 mtb-auto" :style="{ color: item.isDisabled || item.isAbout === '已预约' ? '#c8c9cc' : '#333333' }"> {{ item.timeSlot }}</view>
  103. <view class="font15 mtb-auto ml-auto" :style="{ color: item.isDisabled || item.isAbout === '已预约' ? '#c8c9cc' : '#333333' }"> {{ item.isAbout }}</view>
  104. </template>
  105. </u-checkbox>
  106. </view>
  107. </u-checkbox-group>
  108. </scroll-view>
  109. <u-gap height="10" bgColor="#f5f6f7"></u-gap>
  110. <view class="p10" style="overflow: hidden">
  111. <u-button type="primary" @click="handleSubmit('下一步')" text="下一步" style="width: 100px; float: right"></u-button>
  112. </view>
  113. </view>
  114. </view>
  115. </u-popup>
  116. <u-action-sheet
  117. :actions="sheet.actions"
  118. :show="sheet.show"
  119. cancelText="取消"
  120. :round="10"
  121. :wrapMaxHeight="'50vh'"
  122. :closeOnClickOverlay="true"
  123. :safeAreaInsetBottom="true"
  124. @close="sheet.show = false"
  125. @select="changeSheet"
  126. ></u-action-sheet>
  127. </template>
  128. <script setup>
  129. /*----------------------------------依赖引入-----------------------------------*/
  130. import { onLoad, onShow, onReady, onHide, onLaunch, onUnload, onNavigationBarButtonTap, onPageScroll } from "@dcloudio/uni-app";
  131. import { ref, reactive, computed, getCurrentInstance, toRefs, inject } from "vue";
  132. /*----------------------------------接口引入-----------------------------------*/
  133. import { MeetingRoomList, MeetingRoomReservationList } from "@/api/business/meeting.js";
  134. import { doorApi } from "@/api/business/door.js";
  135. /*----------------------------------组件引入-----------------------------------*/
  136. import timeSlot from "./components/timeSlot.vue";
  137. import switchSlot from "./components/switchSlot.vue";
  138. /*----------------------------------store引入-----------------------------------*/
  139. import { useStores, systemStores } from "@/store/modules/index";
  140. /*----------------------------------公共方法引入-----------------------------------*/
  141. /*----------------------------------公共变量-----------------------------------*/
  142. const { proxy } = getCurrentInstance();
  143. const useStore = useStores();
  144. const systemStore = systemStores();
  145. /*----------------------------------变量声明-----------------------------------*/
  146. const state = reactive({
  147. loading: false,
  148. dataList: [],
  149. pageSize: 20,
  150. total: 0,
  151. form: {
  152. date: proxy.$dayjs().format("YYYY-MM-DD"),
  153. meetingRoomName: "",
  154. },
  155. formData: [
  156. {
  157. type: "switchTime",
  158. prop: "date",
  159. label: "时间",
  160. fontSize: "16",
  161. data: [],
  162. },
  163. ],
  164. popup: {
  165. show: false,
  166. type: "",
  167. list: {},
  168. },
  169. sheet: {
  170. show: false,
  171. title: "",
  172. actions: [],
  173. },
  174. checkboxValue: [],
  175. checkboxList: [],
  176. scrollIntoView: "",
  177. });
  178. const { loading, dataList, pageSize, total, form, formData, popup, sheet, checkboxValue, checkboxList, scrollIntoView } = toRefs(state);
  179. /** 初始化 */
  180. function init() {
  181. state.checkboxValue = [];
  182. state.checkboxList = [];
  183. state.loading = true;
  184. MeetingRoomReservationList({
  185. date: state.form.date + " 00:00:00",
  186. meetingRoomName: state.form.meetingRoomName,
  187. })
  188. .then((requset) => {
  189. if (requset.status === "SUCCESS") {
  190. state.dataList = requset.data;
  191. state.total = requset.data.length;
  192. state.loading = false;
  193. }
  194. })
  195. .catch((err) => {
  196. state.loading = false;
  197. });
  198. state.checkboxList = getAllTimesDay(state.form.date, 30);
  199. }
  200. /** 获取当天时间 */
  201. function getAllTimesDay(day, min) {
  202. let defaultList = [];
  203. // 获取当天开始的时间
  204. const startOfDay = proxy.$dayjs(day).startOf("day");
  205. const endOfDay = proxy.$dayjs(day).endOf("day");
  206. // 循环半小时直到当天结束
  207. for (let currentTime = startOfDay; currentTime.isBefore(endOfDay); currentTime = currentTime.add(min, "minute")) {
  208. let isAfter = currentTime.add(min, "minute").isAfter(endOfDay); //当前时间是否在结束时间之后(true|false)
  209. let startTime = currentTime.add(0, "minute").format("YYYY-MM-DD HH:mm:ss"); //获取开始时间
  210. let endTime = isAfter ? endOfDay.format("YYYY-MM-DD HH:mm:ss") : currentTime.add(min, "minute").format("YYYY-MM-DD HH:mm:ss"); //获取结束时间
  211. let timeSlot = proxy.$dayjs(startTime).format("HH:mm") + " - " + proxy.$dayjs(endTime).format("HH:mm"); //获取开始时间和结束时间“时、分”
  212. const array = {
  213. id: defaultList.length + 1,
  214. startTime: startTime,
  215. endTime: endTime,
  216. timeSlot: timeSlot,
  217. isDisabled: false,
  218. isAbout: "",
  219. isDisabledColor: "#FFFFFF",
  220. isDisabledFontColor: "#333333",
  221. }; //此返回值(不可删除)可叠加
  222. //判断当前时间是否相同或在其之后
  223. if (proxy.$dayjs().isSameOrAfter(startTime)) {
  224. array.isAbout = "不可预约";
  225. array.isDisabled = true;
  226. }
  227. defaultList.push(array);
  228. }
  229. return defaultList;
  230. }
  231. /** 复选框改变事件 */
  232. function checkboxChange(e, index) {
  233. if (e.length > 1) {
  234. const startOfDay = proxy.$dayjs(e[0]);
  235. const endOfDay = proxy.$dayjs(e[e.length - 1]);
  236. for (let currentTime = startOfDay; currentTime.isBefore(endOfDay); currentTime = currentTime.add(30, "minute")) {
  237. if (!e.includes(currentTime.format("YYYY-MM-DD HH:mm:ss"))) {
  238. e.push(currentTime.format("YYYY-MM-DD HH:mm:ss"));
  239. }
  240. }
  241. }
  242. state.checkboxValue = e.sort((a, b) => new Date(`${proxy.$dayjs(a).format("YYYY-MM-DD HH:mm:ss")}`) - new Date(`${proxy.$dayjs(b).format("YYYY-MM-DD HH:mm:ss")}`));
  243. }
  244. /** 点击预约 */
  245. function handleSubmit() {
  246. if (!state.checkboxValue.length) {
  247. proxy.$modal.msg("请先选择时间");
  248. return false;
  249. }
  250. systemStore.meetingList.form = {
  251. roomId: state.popup.list.roomId, //房间Id
  252. roomName: state.popup.list.roomName, //会议室名称
  253. startDate: state.checkboxValue[0], //会议开始时间
  254. endDate: state.checkboxValue[state.checkboxValue.length - 1], //会议结束时间
  255. meetingName: useStore.nickName + "预约的会议", //会议名称
  256. initiatorUser: {
  257. contacts: useStore.phonenumber, //联系方式
  258. deptId: useStore.deptId,
  259. email: useStore.email,
  260. id: useStore.userId,
  261. isApprover: false,
  262. name: useStore.nickName, //验证人名称
  263. sex: useStore.sex,
  264. }, //发起人信息
  265. meetingDescribe: "", //会议介绍
  266. users: [], //参会人信息
  267. meetingMode: 0, //会议模式
  268. sendType: ["站内信"], //通知类型(短信)
  269. remark: "", //备注
  270. room: state.popup.list, //会议室信息
  271. meetingFileList: [], //会议文件信息
  272. };
  273. proxy.$tab.navigateTo(`/pages/business/meeting/new/index`);
  274. state.popup.show = false;
  275. }
  276. /** 操作菜单 */
  277. function changeSheet(e) {
  278. if (e.name == "会议室详情") {
  279. proxy.$tab.navigateTo(`/pages/business/meeting/detailed/index?roomId=${state.popup.list.roomId}`).then(() => {});
  280. } else if (e.name == "门禁开门") {
  281. openDoor(e);
  282. } else if (e.name == "我的会议") {
  283. proxy.$tab.navigateTo(`/pages/business/meeting/my/index`).then(() => {});
  284. }
  285. }
  286. /**
  287. * @门禁开门
  288. */
  289. function openDoor(e) {
  290. doorApi()
  291. .control({
  292. productCode: "502_USKY",
  293. deviceUuid: e.deviceUuid,
  294. commandCode: "door_onoff",
  295. commandValue: 1,
  296. })
  297. .then((item2) => {
  298. proxy.$modal.msg("开门成功");
  299. })
  300. .catch((err) => {
  301. console.log(err);
  302. });
  303. }
  304. /** 操作菜单 */
  305. function handleSheet(show, type) {
  306. state.sheet.show = show;
  307. if (type === "rightMore") {
  308. state.sheet.actions = [
  309. {
  310. name: "我的会议",
  311. value: "",
  312. type: "meeting-my",
  313. },
  314. ];
  315. } else if (type === "popupMore") {
  316. state.sheet.actions = [
  317. {
  318. name: "门禁开门",
  319. value: "",
  320. type: "meeting-room",
  321. },
  322. {
  323. name: "会议室详情",
  324. value: "",
  325. type: "meeting-details",
  326. },
  327. ];
  328. }
  329. }
  330. /** 操作弹窗 */
  331. function handlePopup(show, type, list) {
  332. state.popup.show = show;
  333. state.popup.type = type;
  334. state.popup.list = list;
  335. if (type === "aboutMeeting") {
  336. list.dmMeetingList.forEach((e) => {
  337. let startTime = proxy.$dayjs(e.startDate).add(0, "minute").format("YYYY-MM-DD HH:mm:ss");
  338. let endTimeNum = e.endDate.indexOf("59") != -1 ? -29.59 : -30;
  339. let endTime = proxy.$dayjs(e.endDate).add(endTimeNum, "minute").format("YYYY-MM-DD HH:mm:ss");
  340. state.checkboxList.forEach((f) => {
  341. if (proxy.$dayjs(f.startTime).isBetween(startTime, endTime, null, "[]")) {
  342. f.isDisabledColor = proxy.$settingStore.themeColor.color;
  343. f.isDisabledFontColor = "#FFFFFF";
  344. f.isAbout = "已预约";
  345. }
  346. });
  347. });
  348. state.scrollIntoView = "";
  349. setTimeout(() => {
  350. state.checkboxList.some((e) => {
  351. if (e.isDisabled === false) {
  352. state.scrollIntoView = "item" + e.id;
  353. return true;
  354. }
  355. return false;
  356. });
  357. });
  358. }
  359. }
  360. /** 操作重置 */
  361. function resetSwitch() {
  362. state.form = {
  363. date: proxy.$dayjs().format("YYYY-MM-DD"),
  364. meetingRoomName: "",
  365. };
  366. init();
  367. }
  368. /**
  369. * @scrollView刷新数据
  370. */
  371. function refresh() {
  372. init();
  373. }
  374. onReady(() => {});
  375. onShow(() => {
  376. //调用系统主题颜色
  377. proxy.$settingStore.systemThemeColor([1]);
  378. init();
  379. });
  380. onLoad((options) => {});
  381. onUnload(() => {});
  382. </script>
  383. <style lang="scss" scoped>
  384. .content-area {
  385. color: #000000;
  386. }
  387. </style>