この記事では、DingTalkの勤怠カレンダーを実装するためのVueの具体的なコードを参考までに共有します。具体的な内容は次のとおりです。 効果マップ上で直接下を見る必要があります GitHub アドレス: vue-calendar-component checkCalendar.vue (サブコンポーネント)<style lang="scss" rel="スタイルシート/scss"> @media スクリーンと (最小幅: 460px) { .wh_item_date:ホバー{ 背景: #71c7a5; カーソル: ポインタ; } } * { マージン: 0; パディング: 0; } .wh_コンテナ{ 最大幅: 410px; マージン: 自動; } li { リストスタイルタイプ: なし; } .wh_top_title { ディスプレイ: フレックス; } .wh_top_title li { カーソル: ポインタ; ディスプレイ: フレックス; 色: #fff; フォントサイズ: 18px; フレックス: 1; コンテンツの中央揃え: 中央; アイテムの位置を中央揃えにします。 高さ: 47px; } .wh_top_title .wh_content_li { カーソル: 自動; フレックス:2.5; 色: 黒; } .wh_content_all { フォントファミリ: -apple-system、BlinkMacSystemFont、「PingFang SC」、 「Helvetica Neue」、STHeiti、「Microsoft Yahei」、Tahoma、Simsun、サンセリフ体。 背景色: 白; 幅: 100%; オーバーフロー: 非表示; パディング下部: 8px; } .wh_content { ディスプレイ: フレックス; flex-wrap: ラップ; パディング: 0 3% 0 3%; 幅: 100%; } .wh_content:最初の子 .wh_content_item_tag、 .wh_content:最初の子 .wh_content_item { 色: #ddd; フォントサイズ: 16px; } .wh_content_item、 wh_content_item_tag { フォントサイズ: 15px; 幅: 13.4%; テキスト配置: 中央; 色: #fff; 位置: 相対的; } .wh_content_item { 高さ: 40px; } .wh_top_tag { 幅: 40px; 高さ: 40px; 行の高さ: 40px; マージン: 自動; ディスプレイ: フレックス; コンテンツの中央揃え: 中央; アイテムの位置を中央揃えにします。 色: 黒; } .wh_item_date { 幅: 30ピクセル; 高さ: 30px; 行の高さ: 30px; マージン: 自動; ディスプレイ: フレックス; コンテンツの中央揃え: 中央; アイテムの位置を中央揃えにします。 色: 黒; .smallDot { 背景色: #f99341; 幅: 5px; 高さ: 5px; 境界線の半径: 50%; テキスト配置: 中央; 左マージン: 13px; } .smallDot1 { 背景色: #1989fa; 幅: 5px; 高さ: 5px; 境界線の半径: 50%; テキスト配置: 中央; 左マージン: 13px; } } .wh_left { 幅: 12px; 高さ: 12px; 上境界線: 2px 実線 #ffffff; 左境界線: 2px 実線 #ffffff; 変換: 回転(-45度); 境界線の色: 黒; } .wh_left:アクティブ、 .wh_right:アクティブ{ 境界線の色: #ddd; } .wh_right { 幅: 12px; 高さ: 12px; 上境界線: 2px 実線 #ffffff; 右境界線: 2px 実線 #ffffff; 変換: 回転(45度); 境界線の色: 黒; } .wh_content_item > .wh_isMark { マージン: 自動; 境界線の半径: 50%; 背景: 青; zインデックス: 2; } .wh_content_item .wh_other_day非表示 { 色: #bfbfbf; } .wh_content_item .wh_want_dayHide { 色: #bfbfbf; } .wh_content_item .wh_isToday { 背景: #77adfa; 境界線の半径: 50%; } .wh_content_item .wh_chose_day { 背景: #1989fa; 境界線の半径: 50%; } </スタイル> <テンプレート> <セクションクラス="wh_container"> <div class="wh_content_all"> <div class="wh_top_title"> <li @click="PreMonth(myDate,false)"> <div class="wh_left"></div> </li> <li class="wh_content_li">{{dateTop}}</li> <li @click="次の月(myDate,false)"> <div class="wh_right"></div> </li> </div> <div class="wh_content"> <div class="wh_content_item" v-for="テキスト内のタグトップ"> <div class="wh_top_tag">{{タグ}}</div> </div> </div> <div class="wh_content"> <div class="wh_content_item" v-for="(item,index) リスト内" @click="clickDay(item,index)"> <div class="wh_item_date" style="display: block" v-bind:class="[{ wh_isMark: item.isMark},{wh_other_dayHide:item.otherMonth!=='nowMonth'},{wh_want_dayHide:item.dayHide},{wh_isToday:item.isToday},{wh_chose_day:item.chooseDay},setClass(item)]"> {{item.id}} <!--これは異常と正常を制御する小さな点です--> <span v-for="(date,index) in dateList" :key="index"> <span v-if="date.offDutyTime&&date.onDutyTime&&formatDate(date.recordDate)==item.date&&(isLate(date.serverEndTime,date.offDutyTime)||isLate(date.onDutyTime,date.serverStartTime))"> <div class="smallDot"></div> </span> <span v-if="date.offDutyTime&&date.onDutyTime&&formatDate(date.recordDate)==item.date&&!isLate(date.serverEndTime,date.offDutyTime)&&!isLate(date.onDutyTime,date.serverStartTime)"> <div class="smallDot1"></div> </span> </span> </div> </div> </div> </div> </セクション> </テンプレート> <スクリプト> 「./calendar」からtimeUtilをインポートします。 エクスポートデフォルト{ データ() { 戻る { 私の日付: [], リスト: [], 履歴選択: [], 日付トップ: "", ログインNannyUser: {}, ログインGzhユーザー: {}, 日付リスト: [] }; }, 小道具: { マーク日付: { タイプ: 配列、 デフォルト: () => [] }, マーク日付詳細: { タイプ: 配列、 デフォルト: () => [] }, テキストトップ: { タイプ: 配列、 デフォルト: () => ["月", "火", "水", "木", "金", "土", "日"] }, 日曜日開始: { タイプ: ブール値、 デフォルト: () => false }, 前日非表示: { タイプ: 文字列、 デフォルト: `0` }, 未来の日非表示: { タイプ: 文字列、 デフォルト: `2554387200` }, 参加希望ID: { デフォルト: null } }, 作成された() { $this = this; とします。 this.getLoginAllUser("nanny", {}, function (){//これは私のビジネスなので、削除してください}); this.intStart(); // データを初期化します this.myDate = new Date(); }, メソッド: { isLate(str, str1){//2 時間、分、秒の大きさを判断します return new Date((this.formatDates(new Date()) + " " + str).replace(/-/g, '/')) > new Date((this.formatDates(new Date()) + " " + str1).replace(/-/g, '/')); }, formatDate(日付) { date = typeof date === 'string' ? new Date(date.replace(/\-/g, '/')) : date; date.getFullYear() + '/' + (date.getMonth() + 1) + '/' を返します。 + 日付.getDate(); }, intStart() { timeUtil.sundayStart = this.sundayStart; }, setClass(データ) { obj = {} とします。 obj[data.markClassName] = data.markClassName; obj を返します。 }, クリック日(アイテム、インデックス) { if (item.otherMonth === "nowMonth" && !item.dayHide) { this.getList(this.myDate、item.date); } if (item.otherMonth !== "nowMonth") { item.otherMonth === "前月" ? this.PreMonth(item.date) : this.NextMonth(item.date); } }, 選択した月(日付、isSelectedDay = true) { 日付 = timeUtil.dateFormat(日付); this.myDate = 新しい Date(date); this.$emit("changeMonth", timeUtil.dateFormat(this.myDate)); if (isSelectedDay) { this.getList(this.myDate、date、isSelectedDay); } それ以外 { this.getList(this.myDate); } }, 前月(日付、isSelectedDay = true) { 日付 = timeUtil.dateFormat(日付); this.myDate = timeUtil.getOtherMonth(this.myDate, "preMonth"); this.$emit("changeMonth", timeUtil.dateFormat(this.myDate)); this.axiosPost("/nannyCheckIn/findMonthList.n", {date: this.myDate,joinWishListId: this.joinWishId,}, function (resData) { this.dateList = resData.list; }); if (isSelectedDay) { this.getList(this.myDate、date、isSelectedDay); } それ以外 { this.getList(this.myDate); } }, 次の月(日付、isSelectedDay = true) { 日付 = timeUtil.dateFormat(日付); this.myDate = timeUtil.getOtherMonth(this.myDate, "nextMonth"); this.$emit("changeMonth", timeUtil.dateFormat(this.myDate)); this.axiosPost("/nannyCheckIn/findMonthList.n", {date: this.myDate,joinWishListId: this.joinWishId,}, function (resData) { this.dateList = resData.list; }); if (isSelectedDay) { this.getList(this.myDate、date、isSelectedDay); } それ以外 { this.getList(this.myDate); } }, forMatArgs() { markDate = this.markDate; とします。 markDateMore = this.markDateMore; とします。 markDate = markDate.map(k => { timeUtil.dateFormat(k) を返します。 }); markDateMore = markDateMore.map(k => { k.date = timeUtil.dateFormat(k.date); k を返します。 }); [markDate, markDateMore]を返します。 }, getList(日付、chooseDay、isSelectedDay = true) { const [markDate, markDateMore] = this.forMatArgs(); this.dateTop = `${date.getFullYear()}年${date.getMonth() + 1}月`; arr = timeUtil.getMonthList(this.myDate); とします。 (i = 0 とします; i < arr.length; i++) { markClassName = "" とします。 k = arr[i]とします。 k.chooseDay = false; 定数nowTime = k.date; 定数 t = new Date(nowTime).getTime() / 1000; //各日の授業を見る (const c of markDateMore) { c.date === nowTime の場合 { マーククラス名 = c.className || ""; } } //クラスを設定するために選択した日をマークする k.markClassName = マーククラス名; k.isMark = markDate.indexOf(nowTime) > -1; //特定の日を選択することはできません k.dayHide = t < this.agoDayHide || t > this.futureDayHide; もしk.isTodayであれば{ this.$emit("isToday", nowTime); } flag = !k.dayHide && k.otherMonth === "nowMonth" とします。 if (chooseDay && chooseDay === nowTime && flag) { this.$emit("choseDay", nowTime); this.historyChose.push(nowTime); k.chooseDay = true; } それ以外の場合 ( this.historyChose[this.historyChose.length - 1] === nowTime && !選択日 && フラグ ){ k.chooseDay = true; } } this.list = arr; } }, マウント() { this.getList(this.myDate); this.axiosPost("/nannyCheckIn/findMonthList.n",{//Business、必要に応じてjoinWishListIdを変更します: this.joinWishId、 }, 関数 (resData) { this.dateList = resData.list; }); }, 時計: マーク日付: { ハンドラ(val, oldVal) { this.getList(this.myDate); }, 深い: 本当 }, マーク日付詳細: { ハンドラ(val, oldVal) { this.getList(this.myDate); }, 深い: 本当 }, 前日非表示: { ハンドラ(val, oldVal) { this.getList(this.myDate); }, 深い: 本当 }, 未来の日非表示: { ハンドラ(val, oldVal) { this.getList(this.myDate); }, 深い: 本当 }, 日曜日開始: { ハンドラ(val, oldVal) { この関数は、次のように開始します。 this.getList(this.myDate); }, 深い: 本当 }, joinWishId: 作業順序を切り替えてデータハンドラーを変更する必要があるため、これをリッスンします(val, oldVal) { this.axiosPost("/nannyCheckIn/findMonthList.n", { 参加ウィッシュリストID: val, }, 関数 (resData) { this.dateList = resData.list; }); }, 深い: 本当 } } }; </スクリプト> calendar.js (日付ツールクラス)エクスポートデフォルト{ // 月の日数 getDaysInOneMonth(date) { 年 = date.getFullYear(); 月を date.getMonth() で返します。 const d = new Date(年, 月, 0); d.getDate() を返します。 }, // いくつか空 getMonthweek(date) { 年 = date.getFullYear(); 月を date.getMonth() で返します。 const dateFirstOne = new Date(年 + '/' + 月 + '/1'); this.sundayStart を返しますか? dateFirstOne.getDay() == 0 ? 7 : dateFirstOne.getDay() : dateFirstOne.getDay() == 0 ? 6 : dateFirstOne.getDay() - 1; }, /** * 現在の日付の前月または翌月を取得します */ getOtherMonth(date, str = 'nextMonth') { const timeArray = this.dateFormat(date).split('/'); 定数年 = timeArray[0]; 定数月 = timeArray[1]; 定数日 = timeArray[2]; year2 = 年とします。 月2とします。 if (str === 'nextMonth') { month2 = parseInt(月) + 1; (月2 == 13)の場合{ year2 = parseInt(year2) + 1; 月2 = 1; } } それ以外 { month2 = parseInt(月) - 1; (月2 == 0)の場合{ year2 = parseInt(year2) - 1; 月2 = 12; } } day2 = day とします。 const days2 = new Date(year2, month2, 0).getDate(); (day2 > days2) の場合 { 2日目 = 日数2; } (月2 < 10) { 月2 = '0' + 月2; } (2日目<10)の場合{ 2日目 = '0' + 2日目; } 定数 t2 = 年2 + '/' + 月2 + '/' + 日2; 新しいDate(t2)を返します。 }, // 先月末の日付 getLeftArr(date) { 定数arr = []; const leftNum = this.getMonthweek(date); const num = this.getDaysInOneMonth(this.getOtherMonth(date, 'preMonth')) - leftNum + 1; preDate = this.getOtherMonth(date, 'preMonth'); // 先月は何日目に始まりましたかfor (let i = 0; i < leftNum; i++) { const nowTime = preDate.getFullYear() + '/' + (preDate.getMonth() + 1) + '/' + (num + i); arr.push({ id: 数字 + i, 日付: 現在時刻、 isToday: false、 その他の月: 'preMonth', }); } arr を返します。 }, // 翌月末の日付 getRightArr(date) { 定数arr = []; const nextDate = this.getOtherMonth(date, 'nextMonth'); const leftLength = this.getDaysInOneMonth(date) + this.getMonthweek(date); const _length = 7 - 左の長さ % 7; (i = 0; i < _length; i++) の場合 { const nowTime = nextDate.getFullYear() + '/' + (nextDate.getMonth() + 1) + '/' + (i + 1); arr.push({ id: i + 1, 日付: 現在時刻、 isToday: false、 その他の月: '翌月', }); } arr を返します。 }, // 日付のフォーマット dateFormat(date) { date = typeof date === 'string' ? new Date(date.replace(/\-/g, '/')) : date; date.getFullYear() + '/' + (date.getMonth() + 1) + '/' を返します。 + 日付.getDate(); }, // 前月と翌月を除いた特定の月のリストを取得する getMonthListNoOther(date) { 定数arr = []; const num = this.getDaysInOneMonth(日付); 年 = date.getFullYear(); 月を date.getMonth() で返します。 toDay = this.dateFormat(新しい Date()); (i = 0; i < num; i++ とします) { const nowTime = 年 + '/' + 月 + '/' + (i + 1); arr.push({ id: i + 1, 日付: 現在時刻、 isToday: toDay === nowTime、 その他の月: 'nowMonth', }); } arr を返します。 }, // レンダリングする月のリストを取得する getMonthList(date) { [ ...this.getLeftArr(日付), ...this.getMonthListNoOther(日付), ...this.getRightArr(日付) ] を返します。 }, // デフォルトは月曜日です sundayStart: false, }; 次にそれをコンポーネントにインポートします './checkCalendar' から nCalendar をインポートします。 エクスポートデフォルト (Vue) => { Vue.component("nCalendar", nCalendar); } 次にそれをページに適用します <style lang="scss" rel="スタイルシート/scss"> .nカレンダー{ .detailDiv { マージン: 20px 0; .imgDiv { 画像 { 幅: 60ピクセル; 高さ: 60px; } } .時間区分{ 背景色: 白; パディング上部: 10px; .clockStyle { フォントサイズ: 16px; 色: #4b90ed; } .時間テキスト{ フォントサイズ: 14px; 左マージン: 5px; } } .stepDiv{ .tagDiv { 上マージン: 10px; } } } } </スタイル> <テンプレート> <div class="nCalender"> <ナビゲーションバー :showLeft="true" :borderLine=true 背景="#f2f2f2" title="出勤カレンダー"> <div @click="$router.push('/h5nAddCard')" slot="right">カードを追加</div> </navBar> <van-field label="作業指示書を選択" v-if="list.length>1" :value="obj1!=null&&obj1.joinWishId!=null?obj1.joinWishId:null"> <selectJoinTemp slot="input" name="joinWishId" name1="auditUserId" v-model="obj1" :isDefault="true"/> </ヴァンフィールド> <!--カレンダー--> <div class="CalendarDiv" v-if="obj1&&obj1.joinWishId&&obj1.joinWishId>0"> <nカレンダー :joinWishId="obj1.joinWishId" v-on:choseDay="クリック日" v-on:changeMonth="変更日"/> </div> <div v-if="list.length==0" class="detailDiv" style="text-align: center;color: #bfbfbf"> <div class="imgDiv"> <img src="../img/rest.png"/> </div> <div style="margin-top: 2%"> 契約なし</div> </div> <!--その日の詳細--> <span></span> <div class="detailDiv" v-if="obj!=null&&obj.id>0&&obj.recordDate&&新しい日付(obj.recordDate.replace(/-/g,'/'))<新しい日付()"> <div class="hourDiv"> <バンの列> <バン列オフセット="1"> <van-icon name="時計" class="時計スタイル"/> </バン-コル> <van-col class="hourText">合計労働時間: <span v-if="obj.totalHour!=null">{{obj.totalHour}} 時間</span> <span v-else>なし</span></van-col> </van-row> </div> <div class="stepDiv"> <van-steps direction="vertical" :active="-1"> <ヴァンステップ> <div> サインイン時間 <span v-if="obj.onDutyTime">{{formatMinutes(obj.onDutyTime)}}</span> <span v-else>なし</span> (勤務時間: {{formatMinutes(obj.serverStartTime)}}) </div> <div class="tagDiv"> <van-tag v-if="obj.onDutyTime&&!isLate(obj.onDutyTime,obj.serverStartTime)" ラウンド type="primary">通常</van-tag> <van-tag v-else ラウンド type="warning">遅い</van-tag> </div> </ヴァンステップ> <ヴァンステップ> <div> サインアウト時間 <span v-if="obj.offDutyTime">{{formatMinutes(obj.offDutyTime)}}</span> <span v-else>なし</span> (勤務時間終了: {{formatMinutes(obj.serverEndTime)}}) </div> <div class="tagDiv"> <van-tag v-if="obj.offDutyTime&&isLate(obj.serverEndTime,obj.offDutyTime)" ラウンド type="warning">早めに出発</van-tag> <van-tag v-if="obj.offDutyTime&&!isLate(obj.serverEndTime,obj.offDutyTime)" ラウンド type="primary">通常</van-tag> </div> </ヴァンステップ> </ヴァンステップ> </div> </div> <div v-if="obj!=null&&obj.id>0&&!obj.offDutyTime&&!obj.onDutyTime" クラス="detailDiv" スタイル="text-align: center;color: #bfbfbf"> <div class="imgDiv"> <img src="../img/rest.png"/> </div> <div style="margin-top: 2%"> その日の出勤記録はありません</div> </div> </div> </テンプレート> <スクリプト> エクスポートデフォルト{ 名前: "nCalender", データ() { 戻る { ログインNannyUser: {}, ログインGzhユーザー: {}, オブジェクト: {}, オブジェクト1: {}, リスト: [], 日付時間: null } }, メソッド: { isLate(str, str1){//2 時間、分、秒の大きさを判断します return new Date((this.formatDates(new Date()) + " " + str).replace(/-/g, '/')) > new Date((this.formatDates(new Date()) + " " + str1).replace(/-/g, '/')); }, clickDay(data){//日を選択 this.dateTemp = data this.axiosPost("/nannyCheckIn/findNowRecord.n", { クエリ日付: データ、 ID: this.obj1.joinWishId }, 関数 (resData) { _this.obj = resData.obj; }); }, changeDate(data){//左または右をクリックして月を切り替えます console.log(data); }, }, マウント() { }, 作成された() { $this = this; とします。 this.getLoginAllUser("nanny", {}, 関数 () { $this.axiosPost("/joinWishList/findNannyCon.n", {}, 関数(resData) { リストを resData に格納します。 resData.list != null && resData.list.length != 0 の場合 { $this.$set($this.obj1, "joinWishId", resData.list[0].id); } $this.axiosPost("/nannyCheckIn/findNowRecord.n", {id: $this.obj1.joinWishId}, 関数(resData) { 戻り値: }); }); }); }, 時計: "obj1.joinWishId": { ハンドラ(newObj, oldObj) { (newObj != oldObj && newObj && newObj != null) の場合 { this.axiosPost("/nannyCheckIn/findNowRecord.n", { クエリ日付: this.dateTemp、 id: 新しいオブジェクト }, 関数 (resData) { this.obj = resData.obj; }); } }, 深い: 本当 }, } } </スクリプト> 上記のコードとほぼ同じです。コピーしてそのまま使用できます。ajax リクエストを変更するだけです。拡張する必要がある場合は、自分で変更してください。 以上がこの記事の全内容です。皆様の勉強のお役に立てれば幸いです。また、123WORDPRESS.COM を応援していただければ幸いです。 以下もご興味があるかもしれません:
|
<<: MySQL のデータベース パフォーマンスに影響を与える要因の説明
>>: 高可用性 Web クラスターを実装するための Keepalived+Nginx+Tomcat サンプル コード
目次構造継承(callで実装)プロトタイプチェーン継承(プロトタイプチェーンの助けを借りて実装)複合...
カーソルの作成まず、MySql でデータ テーブルを作成します。 存在しない場合はテーブルを作成 `...
この記事の冒頭で、以前書いた入門記事の間違いを訂正したいと思います。初心者を再び誤解させないように、...
目次ポート関連の概念:ポートとサービスの関係1: nmapツールが開いているポートを検出する2: n...
mysql テーブル作成 SQL ステートメントMySQL テーブルを作成するための一般的な SQL...
最初のステップは、Python のバージョン番号とインストール パスを確認することです。 上記のビュ...
質問:私のブログのエンコーディングは utf-8 です。ページを開くと空白になっていることもあります...
Linux でバージョン情報を表示する方法。ビット数、バージョン情報、CPU コア情報、CPU 固有...
意味Calcite は、Sql を SqlNode に解析し、次に SqlNode を特定のデータベ...
この記事では、例を使用して、MySQL 外部キーの基本的な機能と使用方法を説明します。ご参考までに、...
text-fill-color とは何を意味しますか?文字通りの意味から言えば、「テキストの塗りつぶ...
1. 概要Docker のイメージはレイヤーで設計されています。各レイヤーは「レイヤー」と呼ばれます...
概要今日は主に、MySQL データベースから binlog ログを正しく削除する方法を紹介します。ロ...
1. マスタースレーブレプリケーションとは何ですか?マスター データベースの DDL および DML...
vmware vSphere 6.5 は vSphere ソフトウェアのクラシック バージョンであ...