index.vue 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. <template>
  2. <ion-page class="list-page">
  3. <ion-header class="header-theme2 header-theme3">
  4. <ion-toolbar>
  5. <ion-buttons slot="start">
  6. <ion-icon :icon="arrowBackOutline()" @click="onBack"></ion-icon>
  7. </ion-buttons>
  8. <ion-title>外出走访签到</ion-title>
  9. </ion-toolbar>
  10. </ion-header>
  11. <ion-content>
  12. <ion-item class="search-item">
  13. 当前时间:{{ dayjs(new Date()).format("YYYY-MM-DD HH:mm") }}
  14. </ion-item>
  15. <div id='signInMap' style=' width: 100%; height: 200px; z-index: 100'></div>
  16. <div class="bw-vue-form">
  17. <div class="form-select">
  18. <ion-label>外出类型<span class="danger">*</span></ion-label>
  19. <ion-select interface="action-sheet" placeholder="请选择外出类型" cancel-text="取消"
  20. id="signinType" v-model="dataModel.signinType" @change="signinTypeChange()">
  21. <ion-select-option v-for="(record,key) in signinTypeList" :key="key"
  22. v-model:value="record.value">
  23. {{ record.name }}
  24. </ion-select-option>
  25. </ion-select>
  26. </div>
  27. <div class="form-select" v-if="dataModel.signinType===1">
  28. <ion-label>走访企业<span class="danger">*</span></ion-label>
  29. <company-select ref="refCompanySelect" @resultInfo="onCompanySelect"></company-select>
  30. </div>
  31. <div class="form-select" v-if="dataModel.signinType===2">
  32. <ion-label>走访人员<span class="danger">*</span></ion-label>
  33. <job-user-select ref="refJobuserSelect" @resultInfo="onJobUserSelect"></job-user-select>
  34. </div>
  35. <div class="form-input">
  36. <ion-label>服务内容</ion-label>
  37. <ion-textarea v-model="dataModel.content" rows="5" cols="20" placeholder="请填写服务内容"></ion-textarea>
  38. </div>
  39. <div class="form-input">
  40. <ion-label>照片</ion-label>
  41. <b-image :file-ref-id="dataModel.signinId" :readonly="false" :is-single="false"></b-image>
  42. </div>
  43. </div>
  44. <div class="btn-box">
  45. <ion-button @click="onSave">确定签到</ion-button>
  46. </div>
  47. </ion-content>
  48. </ion-page>
  49. </template>
  50. <script>
  51. import {defineComponent, reactive, ref, toRefs} from "vue";
  52. import {alertController, onIonViewDidEnter} from "@ionic/vue";
  53. import {useUserStore} from "../../../../store/modules/user";
  54. import dayjs from 'dayjs';
  55. import {getPosition} from "@/utils/position";
  56. import thIcon from "@/assets/icon/th.jpg"
  57. import {arrowBackOutline} from "ionicons/icons";
  58. import {useRouter} from "vue-router";
  59. import {saveSignin} from "@/api/position";
  60. import CompanySelect from "@/components/companySelect.vue";
  61. import JobUserSelect from "@/components/jobUserSelect.vue";
  62. import {getSysDictionaryList} from "../../../../api/system/dictionary";
  63. import {v4 as uuidv4} from 'uuid';
  64. import BImage from "@/components/bImage.vue";
  65. const presentAlert = async (header, message) => {
  66. const alert = await alertController.create({
  67. header: header,
  68. message: message,
  69. buttons: [
  70. '确定'
  71. ],
  72. });
  73. await alert.present();
  74. }
  75. export default defineComponent({
  76. name: 'signInMap',
  77. components: {CompanySelect, JobUserSelect, BImage},
  78. methods: {
  79. arrowBackOutline() {
  80. return arrowBackOutline
  81. }, dayjs
  82. },
  83. setup() {
  84. const router = useRouter()
  85. const userStore = useUserStore();
  86. const userInfo = ref(userStore.getUserInfo);
  87. const position = reactive({
  88. longitude: null,
  89. latitude: null
  90. });
  91. const T = window.T;
  92. const zoom = 14;
  93. let map = null;
  94. let label = null;
  95. let marker = null;
  96. const refCompanySelect = ref();
  97. const refJobuserSelect = ref();
  98. const formState = reactive({
  99. dataModel: {
  100. signinId: null,
  101. signinType: null,
  102. companyID: null,
  103. companyName: '',
  104. jobuserID: null,
  105. longitude: null,
  106. latitude: null,
  107. content: '',
  108. createUserID: userInfo.value.userID
  109. }
  110. });
  111. const signinTypeList = ref([]);
  112. const getSigninTypeList = async function () {
  113. const signinTypeListResult = await getSysDictionaryList("SigninType");
  114. signinTypeList.value = signinTypeListResult;
  115. }
  116. const setMarker = () => {
  117. // 删除点
  118. if (marker != null) {
  119. map.removeOverLay(marker);
  120. }
  121. //设置显示地图的中心点和级别
  122. map.centerAndZoom(new T.LngLat(114.40, 23.08), zoom);
  123. // 获取定位
  124. getPosition().then((data) => {
  125. if (data.longitude && data.latitude) {
  126. position.longitude = data.longitude;
  127. position.latitude = data.latitude;
  128. // 设置中心点
  129. map.centerAndZoom(new T.LngLat(position.longitude, position.latitude), zoom);
  130. const icon = new T.Icon({
  131. iconUrl: thIcon,
  132. iconSize: new T.Point(30, 30),
  133. iconAnchor: new T.Point(10, 56)
  134. })
  135. label = new T.Label({
  136. text: userInfo.value.siteUserName, //文本标注的内容
  137. position: new T.LngLat(position.longitude, position.latitude), //文本标注的地理位置
  138. offset: new T.Point(-40, 20) //文本标注的位置偏移值
  139. })
  140. const point = new T.LngLat(position.longitude, position.latitude, {
  141. icon: icon
  142. })
  143. // 创建标注
  144. marker = new T.Marker(point);
  145. //向地图上标记
  146. map.addOverLay(label);
  147. map.addOverLay(marker);
  148. }
  149. })
  150. }
  151. const initMap = () => {
  152. //初始化地图对象
  153. map = new T.Map("signInMap");
  154. setMarker();
  155. }
  156. function onBack() {
  157. router.go(-1)
  158. }
  159. // 保存
  160. function onSave() {
  161. if(!(position.latitude && position.longitude)){
  162. presentAlert('提示', '获取位置信息失败');
  163. return false;
  164. }
  165. if (!formState.dataModel.signinType) {
  166. presentAlert('提示', '请选择打卡类型');
  167. return false;
  168. }
  169. if (formState.dataModel.signinType === 1 && !formState.dataModel.companyID) {
  170. presentAlert('提示', '请选择走访企业');
  171. return false;
  172. }
  173. if (formState.dataModel.signinType === 2 && !formState.dataModel.jobuserID) {
  174. presentAlert('提示', '请选择走访人员');
  175. return false;
  176. }
  177. formState.dataModel.latitude = position.latitude;
  178. formState.dataModel.longitude = position.longitude;
  179. // 发送请求
  180. saveSignin(formState.dataModel).then(() => {
  181. onBack();
  182. presentAlert('提示', '签到成功');
  183. });
  184. }
  185. const onCompanySelect = (data) => {
  186. formState.dataModel.companyID = data.value;
  187. };
  188. const onJobUserSelect = (data) => {
  189. formState.dataModel.jobuserID = data.value;
  190. };
  191. const signinTypeChange = () => {
  192. formState.dataModel.companyID = '';
  193. formState.dataModel.jobuserID = '';
  194. };
  195. const resetData = function () {
  196. formState.dataModel.signinId = uuidv4();
  197. formState.dataModel.companyID = null;
  198. formState.dataModel.jobuserID = '';
  199. formState.dataModel.signinType = null;
  200. formState.dataModel.longitude = null;
  201. formState.dataModel.latitude = null;
  202. formState.dataModel.content = '';
  203. };
  204. onIonViewDidEnter(() => {
  205. resetData();
  206. initMap();
  207. getSigninTypeList();
  208. });
  209. return {
  210. ...toRefs(formState),
  211. refCompanySelect,
  212. refJobuserSelect,
  213. signinTypeList,
  214. onBack,
  215. onSave,
  216. onCompanySelect,
  217. onJobUserSelect,
  218. getSigninTypeList,
  219. signinTypeChange
  220. }
  221. }
  222. });
  223. </script>
  224. <style lang="less">
  225. .btn-box {
  226. width: 100%;
  227. display: flex;
  228. justify-content: center;
  229. padding: 15px;
  230. }
  231. </style>