postEdit.vue 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616
  1. <template>
  2. <ion-page class="list-page">
  3. <ion-header class="header-theme2">
  4. <ion-toolbar>
  5. <ion-buttons slot="start">
  6. <ion-icon :icon="arrowBackOutline" @click="back"></ion-icon>
  7. </ion-buttons>
  8. <ion-title>
  9. 岗位信息收集
  10. </ion-title>
  11. </ion-toolbar>
  12. </ion-header>
  13. <ion-content>
  14. <form autocomplete="off">
  15. <div class="bw-vue-form">
  16. <ion-list>
  17. <div class="form-title">基本信息</div>
  18. <div class="form-input">
  19. <ion-label>岗位名称<span class="danger">*</span></ion-label>
  20. <div>
  21. <ion-input placeholder="请输入岗位" label-placement="stacked" style="float: left;width:78%;"
  22. @click="onOpenPost" v-model="dataModel.professionName" class="custom" readonly >
  23. </ion-input>
  24. <ion-item style="width:22%;float: right;padding:0px;margin: 0px;">
  25. <post-selection-like ref="refPostSelectionLike" @resultInfo="onResultInfo"></post-selection-like>
  26. </ion-item>
  27. </div>
  28. <!-- <ion-note v-show="isCommit&&v$.dataModel.professionID.$error" class="danger" >请选择岗位</ion-note>-->
  29. </div>
  30. <div style="width: 100%;overflow: hidden;"></div>
  31. <div class="form-input">
  32. <ion-label>工种名称<span class="danger">*</span></ion-label>
  33. <div>
  34. <ion-input placeholder="请选择工种" label-placement="stacked" style="float: left;width:78%;"
  35. v-model="dataModel.workCategoryName" class="custom" readonly >
  36. </ion-input>
  37. <ion-item style="width:22%;float: right;padding:0px;margin: 0px;">
  38. <work-category-selection :WorkCategoryID="dataModel.workCode" @SetWorkCategoryID="onSetWorkCategoryID"></work-category-selection>
  39. </ion-item>
  40. </div>
  41. <!-- <ion-note slot="error" >请选择工种</ion-note>-->
  42. </div>
  43. <div style="width: 100%;overflow: hidden;"></div>
  44. <div class="form-input">
  45. <ion-label>招聘数量(人)<span class="danger">*</span></ion-label>
  46. <ion-input type="number" placeholder="请输入招聘数量" label-placement="stacked" :clear-input="true"
  47. v-model="dataModel.recruitCount" class="custom" @ionBlur="recruitCountBlur">
  48. </ion-input>
  49. <!-- <ion-note slot="error">请输入招聘数量</ion-note>-->
  50. </div>
  51. <div class="form-input">
  52. <ion-label>招聘日期<span class="danger">*</span></ion-label>
  53. <div>
  54. <ion-datetime-button datetime="startTime" style="float:left;"></ion-datetime-button>
  55. <span style="float:left;padding-top: 5px;">至</span>
  56. <ion-datetime-button datetime="endTime" style="float:left;"></ion-datetime-button>
  57. <ion-modal :keep-contents-mounted="true">
  58. <ion-datetime placeholder="招聘日期" id="startTime"
  59. v-model="dataModel.startTime" :prefer-wheel="true"
  60. dataformatas="YYYY-MM-DD" presentation="date" cancel-text="取消" done-text="确定"
  61. :show-default-buttons="true" style="text-align: left;width: 100%;">
  62. </ion-datetime>
  63. </ion-modal>
  64. <ion-modal :keep-contents-mounted="true">
  65. <ion-datetime placeholder="招聘日期" id="endTime"
  66. v-model="dataModel.endTime" :prefer-wheel="true"
  67. dataformatas="YYYY-MM-DD" presentation="date" cancel-text="取消" done-text="确定"
  68. :show-default-buttons="true" style="text-align: left;width: 100%;">
  69. </ion-datetime>
  70. </ion-modal>
  71. <!-- <ion-note slot="error">招聘开始日期与结束日期不能为空</ion-note>-->
  72. </div>
  73. </div>
  74. <div style="overflow: hidden;width:100%;"></div>
  75. <div class="form-input">
  76. <ion-label>工作地点<span class="danger">*</span></ion-label>
  77. <ion-textarea placeholder="请输入工作地点" :rows="3" label-placement="stacked" :clear-input="true"
  78. v-model="dataModel.jobPlace" class="custom" style="border-bottom: 1px solid #fff2e8;">
  79. </ion-textarea>
  80. <!-- <ion-note slot="error">请输入工作地点</ion-note>-->
  81. </div>
  82. <div class="form-title">
  83. 其他信息
  84. <div style="float: right;">
  85. <ion-label style="color: red;font-size: 14px;" @click="isShow=!isShow">{{isShow?"收起":"展开"}}</ion-label>
  86. </div>
  87. </div>
  88. <div v-show="isShow" >
  89. <div class="form-select">
  90. <ion-label>工作性质</ion-label>
  91. <ion-select interface="action-sheet" placeholder="请选择工作性质" cancel-text="取消" name="workNatureID"
  92. id="workNatureID" v-model="dataModel.workNatureID" style="width: 100%;text-align: left;" >
  93. <ion-select-option v-for="(record,key) in workNatureList" :key="key"
  94. v-model:value="record.value">
  95. {{ record.name }}
  96. </ion-select-option>
  97. </ion-select>
  98. </div>
  99. <div class="form-input">
  100. <ion-label>岗位月薪(元)</ion-label>
  101. <div>
  102. <ion-input type="number" placeholder="请输入金额" label-placement="stacked" style="float:left;width:40%;"
  103. v-model="dataModel.minSalary" class="custom">
  104. </ion-input>
  105. <ion-label style="float:left;width:5%;padding-top: 8px;">至</ion-label>
  106. <ion-input placeholder="请输入金额" label-placement="stacked" style="float:left;width:40%;"
  107. v-model="dataModel.maxSalary" class="custom">
  108. </ion-input>
  109. </div>
  110. </div>
  111. <div style="overflow: hidden;width:100%;"></div>
  112. <div class="form-select">
  113. <ion-label>是否有试用期</ion-label>
  114. <ion-select interface="action-sheet" placeholder="请选择是否有试用期" cancel-text="取消"
  115. id="isTrail" v-model="dataModel.isTrail" style="width: 100%;text-align: left;" @ionChange="onIsTrailChange">
  116. <ion-select-option v-for="(record,key) in isTrailList" :key="key"
  117. v-model:value="record.value">
  118. {{ record.name }}
  119. </ion-select-option>
  120. </ion-select>
  121. </div>
  122. <div class="form-input">
  123. <ion-label>试用期(月)</ion-label>
  124. <ion-input :disabled="!dataModel.isTrail" type="number" placeholder="请输入试用期月数" label-placement="stacked"
  125. v-model="dataModel.trailMonths" class="custom" @ionBlur="trailMonthsBlur">
  126. </ion-input>
  127. </div>
  128. <div class="form-input">
  129. <ion-label>试用期月薪(元)</ion-label>
  130. <div>
  131. <ion-input placeholder="请输入金额" label-placement="stacked" style="float:left;width:40%;"
  132. v-model="dataModel.trailMinSalary" class="custom">
  133. </ion-input>
  134. <ion-label style="float:left;width:5%;padding-top: 8px;">至</ion-label>
  135. <ion-input placeholder="请输入金额" label-placement="stacked" style="float:left;width:40%;"
  136. v-model="dataModel.trailMaxSalary" class="custom">
  137. </ion-input>
  138. </div>
  139. </div>
  140. <div style="overflow: hidden;width:100%;"></div>
  141. <div class="form-select">
  142. <ion-label>工作年限要求</ion-label>
  143. <ion-select interface="action-sheet" placeholder="请选择工作年限" cancel-text="取消"
  144. id="workYear" v-model="dataModel.workYear" style="width: 100%;text-align: left;">
  145. <ion-select-option v-for="(record,key) in workYearList" :key="key"
  146. v-model:value="record.value">
  147. {{ record.name }}
  148. </ion-select-option>
  149. </ion-select>
  150. </div>
  151. <div class="form-select">
  152. <ion-label>学历要求</ion-label>
  153. <ion-select interface="action-sheet" placeholder="请选择学历" cancel-text="取消"
  154. id="cultureRank" v-model="dataModel.cultureRank" style="width: 100%;text-align: left;">
  155. <ion-select-option v-for="(record,key) in cultureRankList" :key="key"
  156. v-model:value="record.value">
  157. {{ record.name }}
  158. </ion-select-option>
  159. </ion-select>
  160. </div>
  161. <div class="form-input">
  162. <ion-label>其他要求</ion-label>
  163. <ion-textarea placeholder="请输入其他要求" :rows="3" label-placement="stacked"
  164. v-model="dataModel.postDesc" class="custom" style="border-bottom: 1px solid #fff2e8;">
  165. </ion-textarea>
  166. </div>
  167. <div class="form-input">
  168. <ion-label>福利待遇</ion-label>
  169. <ion-textarea placeholder="请输入福利待遇" :rows="3" label-placement="stacked"
  170. v-model="dataModel.welfare" class="custom" style="border-bottom: 1px solid #fff2e8;">
  171. </ion-textarea>
  172. </div>
  173. <div class="form-input">
  174. <ion-label>岗位联系人</ion-label>
  175. <ion-input placeholder="请输入岗位联系人" label-placement="stacked"
  176. v-model="dataModel.contactName" class="custom">
  177. </ion-input>
  178. </div>
  179. <div class="form-input">
  180. <ion-label>岗位联系电话</ion-label>
  181. <ion-input placeholder="请输入岗位联系电话" label-placement="stacked"
  182. v-model="dataModel.contactMobile" class="custom">
  183. </ion-input>
  184. </div>
  185. <div class="form-input">
  186. <ion-label>岗位联系人邮箱</ion-label>
  187. <ion-input placeholder="请输入岗位联系人邮箱" label-placement="stacked"
  188. v-model="dataModel.contactEmail" class="custom">
  189. </ion-input>
  190. </div>
  191. </div>
  192. </ion-list>
  193. </div>
  194. </form>
  195. </ion-content>
  196. <ion-footer>
  197. <ion-toolbar>
  198. <ion-button style="width: 100%;" @click="onSave">提交</ion-button>
  199. </ion-toolbar>
  200. </ion-footer>
  201. </ion-page>
  202. </template>
  203. <script lang="ts">
  204. import {computed, defineComponent, reactive, ref, toRefs, watch} from "vue";
  205. import {chevronDownOutline, chevronUpOutline, arrowBackOutline} from 'ionicons/icons';
  206. import {useRoute, useRouter} from "vue-router";
  207. import {alertController, onIonViewDidEnter} from "@ionic/vue";
  208. import {useVuelidate} from "@vuelidate/core";
  209. import {getPostByID,savePost} from "@/api/post";
  210. import {getCompanyById} from "@/api/company";
  211. import {required} from "@vuelidate/validators";
  212. import {getSysDictionaryList} from "@/api/system/dictionary";
  213. import dayjs from "dayjs";
  214. import PostSelectionLike from "@/components/postSelectionLike.vue";
  215. import WorkCategorySelection from "@/components/workCategorySelection.vue";
  216. interface StepParams{
  217. loginUserID: string,
  218. }
  219. interface postModel {
  220. dataModel: any;
  221. }
  222. export default defineComponent({
  223. name: 'PostEdit',
  224. components:{PostSelectionLike,WorkCategorySelection},
  225. setup() {
  226. const router = useRouter();
  227. const route = useRoute();
  228. const isShow = ref<any>(false);
  229. const isEdit = ref<any>(false);
  230. const isCommit = ref<any>(false);
  231. const formState = reactive<postModel>({
  232. dataModel: {
  233. companyID:null,
  234. professionName:null,
  235. professionID:null,
  236. postName:null,
  237. workCategoryName:null,
  238. workCode:null,
  239. workName:null,
  240. recruitCount:null,
  241. startTime:dayjs().format("YYYY-MM-DD"),
  242. endTime:dayjs().format("YYYY-MM-DD"),
  243. jobPlace:null,
  244. minSalary:null,
  245. maxSalary:null,
  246. isTrail:null,
  247. trailMonths:0,
  248. trailMinSalary:null,
  249. trailMaxSalary:null,
  250. workYear:null,
  251. cultureRank:null,
  252. welfare:null,
  253. postDesc:null,
  254. workNatureID:null,
  255. contactName:null,
  256. contactMobile:null,
  257. contactEmail:null,
  258. bonus:null,
  259. loginUserID:''
  260. }});
  261. const rules = computed(() => {
  262. return {
  263. dataModel: {
  264. professionName: {required},
  265. workCategoryName: {required},
  266. recruitCount: {required},
  267. startTime: {required},
  268. endTime: {required},
  269. jobPlace:{required}
  270. }
  271. }
  272. });
  273. const v$ = useVuelidate(rules, formState);
  274. const isTrailList = ref([
  275. {value: true, name: '是'},
  276. {value: false, name: '否'},
  277. ]);
  278. const workYearList = ref([]);
  279. const cultureRankList = ref([]);
  280. const workNatureList = ref([]);
  281. const refPostSelectionLike = ref();
  282. const curStepData = ref<StepParams>({
  283. loginUserID:""
  284. });
  285. const presentAlert = async (message: string) => {
  286. const alert = await alertController.create({
  287. header: '错误!',
  288. message: message,
  289. buttons: [
  290. '确定'
  291. ],
  292. });
  293. await alert.present();
  294. }
  295. const onSetWorkCategoryID = (data: any)=>{
  296. formState.dataModel.workCode = data.value;
  297. formState.dataModel.workCategoryName = data.text;
  298. }
  299. const onSave = async function (){
  300. isCommit.value = true;
  301. const isFormCorrect = await v$.value.$validate();
  302. console.log("当前岗位信息",formState.dataModel);
  303. if (!isFormCorrect) {
  304. await presentAlert('请输入完整信息!');
  305. return null;
  306. }
  307. ifInputAllValid();
  308. if(isCommit.value&&inputValid.value){
  309. formState.dataModel.loginUserID = curStepData.value.loginUserID;
  310. savePost(formState.dataModel).then(result=>{
  311. if(result){
  312. router.push({path: "./postList", query: {reload:1,id:formState.dataModel.companyID,status: 3}});
  313. }
  314. })
  315. }
  316. }
  317. const onResultInfo = (data: any)=>{
  318. formState.dataModel.professionID = data.value;
  319. formState.dataModel.professionName = data.text;
  320. }
  321. const onOpenPost = () => {
  322. refPostSelectionLike.value.onOpen();
  323. }
  324. const back = () => {
  325. router.push({path: "./postList", query: {reload:1,id:formState.dataModel.companyID,status: 2}});
  326. }
  327. const getWorkYearList = async function(){
  328. const data :any = await getSysDictionaryList("WorkYearType");
  329. workYearList.value = data;
  330. console.log(workYearList.value);
  331. }
  332. const getCultureRankList = async function(){
  333. const data:any = await getSysDictionaryList("CultureLevel");
  334. cultureRankList.value = data;
  335. console.log(cultureRankList.value);
  336. }
  337. const getWorkNationList = async function(){
  338. const data:any = await getSysDictionaryList("WorkNature");
  339. workNatureList.value = data;
  340. }
  341. const loadData = async (postID: any,companyID:any,loginUserID:any) => {
  342. isCommit.value =false;
  343. curStepData.value.loginUserID = loginUserID;
  344. await getWorkYearList();
  345. await getCultureRankList();
  346. await getWorkNationList();
  347. const reqData = await getPostByID(postID);
  348. formState.dataModel = reqData;
  349. formState.dataModel.companyID = companyID;
  350. if(postID==null){
  351. const curPostCompany :any = await getCompanyById(companyID,loginUserID);
  352. formState.dataModel.welfare = curPostCompany.bonus;
  353. }
  354. console.log("初始化岗位信息",formState.dataModel);
  355. };
  356. const onIsTrailChange = ()=>{
  357. if(!formState.dataModel.isTrail){
  358. formState.dataModel.trailMonths = 0;
  359. }
  360. }
  361. function isStringInteger(value: string) {
  362. const n = parseInt(value, 10);
  363. return n.toString() === value && Number.isInteger(n);
  364. }
  365. const inputValid = ref(true);
  366. function recruitCountBlur() {
  367. inputValid.value = true;
  368. if (formState.dataModel.recruitCount != null) {
  369. if(!isStringInteger(formState.dataModel.recruitCount)||formState.dataModel.recruitCount<1){
  370. presentAlert("招聘数量必须为一个正整数!");
  371. inputValid.value = false;
  372. }
  373. }
  374. }
  375. function trailMonthsBlur() {
  376. if (formState.dataModel.trailMonths!= null) {
  377. if(!isStringInteger(formState.dataModel.trailMonths)){
  378. formState.dataModel.trailMonths = Math.floor(formState.dataModel.trailMonths);
  379. if(parseInt(formState.dataModel.trailMonths)<0){
  380. formState.dataModel.trailMonths = 0;
  381. }
  382. }
  383. }
  384. }
  385. const ifInputAllValid = ()=>{
  386. let errorMessage = "";
  387. let hasMinSalary = false;
  388. let hasTrailMinSalary = false;
  389. let curMinSalary = 0.0;
  390. let curTrailMinSalary = 0.0;
  391. if(dayjs(formState.dataModel.startTime).isAfter(dayjs(formState.dataModel.endTime))){
  392. errorMessage +="招聘结束日期不能早于开始日期!";
  393. isCommit.value = false;
  394. }
  395. if (formState.dataModel.minSalary!=null) {
  396. hasMinSalary = true;
  397. curMinSalary = parseFloat(formState.dataModel.minSalary);
  398. if(formState.dataModel.minSalary<0){
  399. errorMessage +="岗位最低月薪不能小于0!";
  400. isCommit.value = false;
  401. }
  402. }
  403. if (formState.dataModel.trailMinSalary!=null) {
  404. hasTrailMinSalary = true;
  405. curTrailMinSalary = parseFloat(formState.dataModel.trailMinSalary);
  406. if(formState.dataModel.trailMinSalary<0){
  407. errorMessage +="试用期最低月薪不能小于0!";
  408. isCommit.value = false;
  409. }
  410. }
  411. if (formState.dataModel.maxSalary!=null) {
  412. if(formState.dataModel.maxSalary<0){
  413. errorMessage +="岗位最高月薪不能小于0!";
  414. isCommit.value = false;
  415. }
  416. if(hasMinSalary){
  417. if(parseFloat(formState.dataModel.maxSalary) < curMinSalary){
  418. errorMessage +="岗位最高月薪不能小于岗位最低月薪!";
  419. isCommit.value = false;
  420. }
  421. }
  422. }
  423. if (formState.dataModel.trailMaxSalary!=null) {
  424. if(formState.dataModel.trailMaxSalary<0){
  425. errorMessage +="试用期最高月薪不能小于0!";
  426. isCommit.value = false;
  427. }
  428. if(hasTrailMinSalary){
  429. if(parseFloat(formState.dataModel.trailMaxSalary) < curTrailMinSalary){
  430. errorMessage +="试用期最高月薪不能小于试用期最低月薪!";
  431. isCommit.value = false;
  432. }
  433. }
  434. }
  435. if (formState.dataModel.trailMonths!=null) {
  436. if(formState.dataModel.isTrail&&formState.dataModel.trailMonths<0){
  437. errorMessage +="试用月数不能小于0!";
  438. isCommit.value = false;
  439. }
  440. }
  441. const mobileReg = /^1[3|4|5|6|7|8|9]\d{9}$/;
  442. const landlineReg = /[0-9-()()]{7,18}/;
  443. if(formState.dataModel.contactMobile != null){
  444. if(!mobileReg.test(formState.dataModel.contactMobile)&&!landlineReg.test(formState.dataModel.contactMobile)){
  445. errorMessage += "输入的联系电话有误!";
  446. isCommit.value = false;
  447. }
  448. }
  449. const emailReg = /^[a-z0-9]+([._\\-]*[a-z0-9])*@([a-z0-9]+[-a-z0-9]*[a-z0-9]+.){1,63}[a-z0-9]+$/;
  450. if(formState.dataModel.contactEmail!=""&&formState.dataModel.contactEmail!=null){
  451. if(!emailReg.test(formState.dataModel.contactEmail)){
  452. errorMessage += "输入的邮箱有误!";
  453. isCommit.value = false;
  454. }
  455. }
  456. if(!isCommit.value){presentAlert(errorMessage);}
  457. }
  458. const reload = (postID: any,companyID:any,loginUserID:any) => {
  459. formState.dataModel.recruitCount = null;
  460. loadData(postID,companyID,loginUserID);
  461. }
  462. onIonViewDidEnter(() => {
  463. if (route.query.reload)
  464. reload(route.query.id,route.query.companyID,route.query.loginUserID);
  465. });
  466. return {
  467. ...toRefs(formState),
  468. chevronDownOutline,
  469. chevronUpOutline,
  470. arrowBackOutline,
  471. route,
  472. router,
  473. isShow,
  474. isEdit,
  475. isTrailList,
  476. workYearList,
  477. cultureRankList,
  478. workNatureList,
  479. v$,
  480. refPostSelectionLike,
  481. onOpenPost,
  482. onResultInfo,
  483. onIsTrailChange,
  484. recruitCountBlur,
  485. trailMonthsBlur,
  486. onSetWorkCategoryID,
  487. onSave,
  488. back,
  489. }
  490. }
  491. });
  492. </script>
  493. <style lang="less">
  494. .custom{
  495. --placeholder-color: gray;
  496. --placeholder-opacity: 0.5;
  497. }
  498. .title-item{
  499. margin-left: 15px;
  500. color:#1c3d70 !important;
  501. font-size: 14px !important;
  502. font-weight: bold;
  503. }
  504. ion-item {
  505. --border-width: 0;
  506. --border-style: none;
  507. ion-label, input, ion-select, ion-datetime {
  508. font-size: 14px !important;
  509. }
  510. }
  511. .stepFlex {
  512. margin: 0;
  513. display: flex;
  514. width: 100%;
  515. .stepFlex-item {
  516. position: relative;
  517. flex: 1;
  518. text-align: center;
  519. margin-top: -10px;
  520. .stepFlex-item-label {
  521. padding-top: 60px;
  522. font-size: 14px;
  523. .stepFlex-item-label-title {
  524. margin-top: 30px;
  525. }
  526. .stepFlex-item-label-desc {
  527. margin-top: 5px;
  528. color: #b9b9bd;
  529. }
  530. }
  531. }
  532. .greenCircle {
  533. top: calc(50% - 15px);
  534. left: calc(50% - 4px);
  535. position: absolute;
  536. z-index: 2;
  537. width: 10px;
  538. height: 10px;
  539. border-radius: 50%;
  540. background-color: #31A2FE;
  541. }
  542. .now {
  543. top: calc(50% - 18px);
  544. left: calc(50% - 8px);
  545. position: absolute;
  546. z-index: 3;
  547. width: 16px;
  548. height: 16px;
  549. border-radius: 50%;
  550. background-color: #31A2FE;
  551. border: 4px solid #c5e8f9;
  552. }
  553. .grayCircle {
  554. top: calc(50% - 15px);
  555. left: calc(50% - 4px);
  556. position: absolute;
  557. z-index: 2;
  558. width: 10px;
  559. height: 10px;
  560. border-radius: 50%;
  561. background-color: #ccc;
  562. }
  563. .greenLine {
  564. width: 100%;
  565. top: calc(50% - 11px);
  566. left: calc(50% - 2px);
  567. height: 2px;
  568. background-color: #31A2FE;
  569. position: absolute;
  570. }
  571. .grayLine {
  572. height: 0;
  573. border: 1px dashed #ccc;
  574. width: 100%;
  575. top: calc(50% - 11px);
  576. left: calc(50% - 2px);
  577. position: absolute;
  578. }
  579. }
  580. </style>