时间格式 1899-12-30T02:46:50.000Z 转 hh:mm

问题描述 投票:0回答:1

我正在尝试编辑此 CRUD Web 应用程序,该应用程序使用 Google Sheet 作为数据库、Google Apps 脚本和 Vuetify 我从这个 YouTube 页面获得TechLever

这是我项目的电子表格

我添加它是为了在我的表单时间字段中显示时间类型

<div v-if="fld.type === 'time'">
<v-text-field
v-model="editedItem[fld.key]"
:label="fld.label"
type="time"
:rules="fld.required ? [rules.required]:[]"
></v-text-field>
</div>

它可以工作,但格式看起来不太好..

这是我在进行任何编辑之前的 Apps 脚本的 index.html:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link href="https://cdn.jsdelivr.net/npm/@mdi/[email protected]/css/materialdesignicons.min.css" rel="stylesheet" />
    <script src="https://unpkg.com/vue@3"></script>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vuetify/3.4.8/vuetify-labs.min.js"
        integrity="sha512-5xeIAXqNP/DWGkolQzdPAL042aA4Lb8SCMy/Ju+9yzvf9SzfsbzICQwYyMrhbN8pG8m0LWhMl9BISpIDs8RquQ=="
        crossorigin="anonymous" referrerpolicy="no-referrer"></script>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/vuetify/3.4.8/vuetify-labs.min.css"
        integrity="sha512-VP/8WyNQxaDeiVsCGXh7nLWVPt64+rqoCugT7xhZLhx9F8fTJpjpiCqHqJlhmKAMgyRU8TiAAxJmmxz260R03w=="
        crossorigin="anonymous" referrerpolicy="no-referrer" />
</head>

<body>
    <div id="app"></div>

    <script type="module">
        const { createApp } = Vue;
        const { createVuetify } = Vuetify;

        const vuetify = createVuetify();

        createApp({
            template: "#app-template",
            data: () => ({
                dialog: false,
                dialogDelete: false,
                schema: null,
                prefs: null,
                search: "",
                headers: [],
                rules: {
                    required: (value) => !!value || "Required.",
                },
                dataTable: [],
                editedIndex: -1,
                editedItem: {},
                defaultItem: {},
                snackbar: {
                    text: "",
                    show: false,
                    timeout: 2000,
                    color: "success",
                    multiline: true,
                    vertical: true,
                    right: true,
                    bottom: true,
                },
            }),

            computed: {
                formTitle() {
                    return this.editedIndex === -1 ? "New Item" : "Edit Item";
                },
            },

            watch: {
                dialog(val) {
                    val || this.close();
                },
                dialogDelete(val) {
                    val || this.closeDelete();
                },
            },

            created() {
                this.fetchSchema();
                this.refresh();
            },

            methods: {
                fetchSchema() {
                    google.script.run
                        .withSuccessHandler((res) => {
                            this.schema = res.schema;
                            this.prefs = res.appSettings;
                            const schema = res.schema;
                            this.headers = schema.map((item) => {
                                return {
                                    title: item.label,
                                    key: item.key,
                                    sortable: item.sortable || true,
                                    align: item.align || "start",
                                };
                            });
                            this.headers.push({
                                text: "Actions",
                                key: "actions",
                                sortable: false,
                            });
                            console.log("Headers", this.headers);

                            this.editedItem = schema.reduce((acc, item) => {
                                acc[item.key] = item.defaultValue || "";
                                return acc;
                            }, {});
                            this.defaultItem = this.editedItem;
                        })
                        .withFailureHandler((error) => {
                            console.log(error);
                        })
                        .getAppPrefs();
                },
                initialize() {
                    google.script.run
                        .withSuccessHandler((res) => {
                            this.dataTable = JSON.parse(res);
                            console.log(this.dataTable);
                        })
                        .withFailureHandler((error) => {
                            console.log(error);
                        })
                        .readAllRecords();
                },
                refresh() {
                    google.script.run
                        .withSuccessHandler((res) => {
                            // this.dataTable = JSON.parse(res);
                            let data = JSON.parse(res);
                            // convert date strings to date objects
                            const dateFlds = this.schema.filter(
                                (fld) => fld.type === "date"
                            );
                            data = data.map((item) => {
                                dateFlds.forEach((fld) => {
                                    const dt = new Date(item[fld.key]);
                                    item[fld.key] = `${dt.getFullYear()}-${(
                                        "0" +
                                        (dt.getMonth() + 1)
                                    ).slice(-2)}-${("0" + dt.getDate()).slice(-2)}`;
                                });
                                return item;
                            });
                            this.dataTable = data;
                        })
                        .withFailureHandler((error) => {
                            console.log(error);
                        })
                        .readAllRecords();
                },
                editItem(item) {
                    this.editedIndex = this.dataTable.indexOf(item);
                    this.editedItem = Object.assign({}, item);
                    this.dialog = true;
                },

                deleteItem(item) {
                    this.editedIndex = this.dataTable.indexOf(item);
                    this.editedItem = Object.assign({}, item);
                    this.dialogDelete = true;
                },

                deleteItemConfirm() {
                    this.showSnackbar("Deleting item...", "warning");
                    google.script.run
                        .withSuccessHandler((res) => {
                            console.log(res);
                            this.dataTable.splice(this.editedIndex, 1);
                            this.closeDelete();
                            this.refresh();
                            this.showSnackbar("Item deleted successfully", "success");
                        })
                        .withFailureHandler((error) => {
                            console.log(error);
                        })
                        .deleteRecord(this.editedItem);
                },

                close() {
                    this.dialog = false;
                    this.$nextTick(() => {
                        this.editedItem = Object.assign({}, this.defaultItem);
                        this.editedIndex = -1;
                    });
                },

                closeDelete() {
                    this.dialogDelete = false;
                    this.$nextTick(() => {
                        this.editedItem = Object.assign({}, this.defaultItem);
                        this.editedIndex = -1;
                    });
                },

                save() {
                    this.showSnackbar("Saving item...", "info");

                    if (this.editedIndex > -1) {
                        console.log("Edited Item", this.editedItem);
                        google.script.run
                            .withSuccessHandler((res) => {
                                this.showSnackbar(
                                    `Item saved successfully!\nRefreshing data..`,
                                    "success"
                                );
                                this.refresh();
                                this.resetForm();
                            })
                            .withFailureHandler((error) => {
                                console.log(error);
                            })
                            .updateRecordById(this.editedItem);
                    } else {
                        google.script.run
                            .withSuccessHandler((res) => {
                                this.showSnackbar(
                                    `Item saved successfully!\nRefreshing data..`,
                                    "success"
                                );
                                this.refresh();
                                this.resetForm();
                            })
                            .withFailureHandler((error) => {
                                console.log(error);
                            })
                            .createRecord(this.editedItem);
                    }
                    this.close();
                },
                resetForm() {
                    this.editedItem = Object.assign({}, this.defaultItem);
                    this.editedIndex = -1;
                },
                showSnackbar(text, color) {
                    this.snackbar.text = text;
                    this.snackbar.color = color;
                    this.snackbar.show = true;
                },
            },
        })
            .use(vuetify)
            .mount("#app");
    </script>
    <script type="text/x-template" id="app-template">
            <v-app>
                  <v-data-table
                    :headers="headers"
                    :items="dataTable"
                    :search="search"
                    :sort-by="[{ key: 'calories', order: 'asc' }]"
                    fixed-header
                  >
                    <template v-slot:top>
                      <v-toolbar
                      :elevation="6"
                      >
                        <v-toolbar-title>{{prefs.AppName}}</v-toolbar-title>
    
    
                        <v-text-field
                          v-model="search"
                          prepend-inner-icon="mdi-magnify"
                          density="compact"
                          label="Search"
                          single-line
                          flat
                          hide-details
                          variant="solo-filled"
                       ></v-text-field>
                        <v-spacer></v-spacer>
                        <v-dialog
                          v-model="dialog"
                          max-width="900px"
                        >
                          <template v-slot:activator="{ props }">
                            <v-btn
                              color="blue"
                              dark
                              class="mb-2"
                              v-bind="props"
                              prepend-icon="mdi-plus"
                              variant="elevated"
                            >
                              New Item
                            </v-btn>
    
                          </template>
                          <v-card>
                            <v-card-title>
                              <span class="text-h5">{{ formTitle }}</span>
                            </v-card-title>
    
                            <v-card-text>
                              <v-container>
                                <v-row>
                                <v-col
                                        v-for="fld in schema"
                                        :key="fld.key"
                                        cols="12"
                                        sm="6"
                                        md="4"
                                    >
    
                                      <div v-if="fld.type === 'text'">
                                          <v-text-field
                                              v-model="editedItem[fld.key]"
                                              :label="fld.label"
                                              :rules="fld.required ? [rules.required]:[]"
                                          ></v-text-field>
                                      </div>
                                      <div v-if="fld.type === 'textarea'">
                                          <v-textarea
                                              v-model="editedItem[fld.key]"
                                              :label="fld.label"
                                              :rules="fld.required ? [rules.required]:[]"
                                          ></v-textarea>
                                      </div>
                                      <div v-if="fld.type === 'select'">
                                          <v-select
                                              v-model="editedItem[fld.key]"
                                              :label="fld.label"
                                              :items="fld.options.split(',')"
                                              :rules="fld.required ? [rules.required]:[]"
                                          ></v-select>
                                      </div>
                                      <div v-if="fld.type === 'checkbox'">
                                          <v-checkbox
                                              v-model="editedItem[fld.key]"
                                              :label="fld.label"
                                              :rules="fld.required ? [rules.required]:[]"
                                          ></v-checkbox>
                                      </div>
                                      <div v-if="fld.type === 'radio'">
                                          <v-radio-group inline v-model="editedItem[fld.key]" :rules="fld.required ? [rules.required]:[]">
                                              <template v-slot:label>
                                                <div>{{fld.label}}</div>
                                              </template>
                                              <v-radio
                                              v-for="opt in fld.options.split(',')"
                                              :key="opt"
                                              :label="opt"
                                              :value="opt"
                                          ></v-radio>
                                            </v-radio-group>
                                      </div>
                                      <div v-if="fld.type === 'date'">
                                          <v-text-field
                                              v-model="editedItem[fld.key]"
                                              :label="fld.label"
                                              type="date"
                                              :rules="fld.required ? [rules.required]:[]"
                                          ></v-text-field>
                                      </div>
                                      <div v-if="fld.type === 'number'">
                                          <v-text-field
                                              v-model="editedItem[fld.key]"
                                              :label="fld.label"
                                              type="number"
                                              :min="fld.min"
                                              :max="fld.max"
                                              :rules="fld.required ? [rules.required]:[]"
                                          ></v-text-field>
                                      </div>
    
                                    </v-col>
    
                                </v-row>
                              </v-container>
                            </v-card-text>
    
                            <v-card-actions>
                              <v-spacer></v-spacer>
                              <v-btn
                                color="blue-darken-1"
                                variant="text"
                                @click="close"
                              >
                                Cancel
                              </v-btn>
                              <v-btn
                                color="blue-darken-1"
                                variant="text"
                                @click="save"
                              >
                                Save
                              </v-btn>
                            </v-card-actions>
                          </v-card>
                        </v-dialog>
                        <v-dialog v-model="dialogDelete" max-width="500px">
                          <v-card>
                            <v-card-title class="text-h5">Are you sure you want to delete this item?</v-card-title>
                            <v-card-actions>
                              <v-spacer></v-spacer>
                              <v-btn color="blue-darken-1" variant="text" @click="closeDelete">Cancel</v-btn>
                              <v-btn color="blue-darken-1" variant="text" @click="deleteItemConfirm">OK</v-btn>
                              <v-spacer></v-spacer>
                            </v-card-actions>
                          </v-card>
                        </v-dialog>
                      </v-toolbar>
                    </template>
                    <template v-slot:item.rating="{ item }">
                      <v-rating
                        :model-value="item.rating"
                        color="blue-darken-2"
                        density="compact"
                        size="small"
                        readonly
                      ></v-rating>
                    </template>
                    <template v-slot:item.amount="{ item }">
                      <div class="text-end">
                          {{ item.amount.toLocaleString(prefs.Locale, {
                              style: "currency",
                              currency: prefs.Currency,
                          }) }}
                      </div>
                    </template>
                    <template v-slot:item.amount1="{ item }">
                      <div class="text-end">
                          {{ item.amount1.toLocaleString(prefs.Locale, {
                              style: "currency",
                              currency: prefs.Currency,
                          }) }}
                      </div>
                    </template>
                    <template v-slot:item.amount2="{ item }">
                      <div class="text-end">
                          {{ item.amount2.toLocaleString(prefs.Locale, {
                              style: "currency",
                              currency: prefs.Currency,
                          }) }}
                      </div>
                    </template>
                    <template v-slot:item.date="{ item }">
                      <div class="text-center">
                          {{ new Date(item.date).toLocaleDateString(prefs.Locale) }}
                      </div>
                      </template>
                      <template v-slot:item.date1="{ item }">
                          <div class="text-center">
                              {{ new Date(item.date1).toLocaleDateString(prefs.Locale) }}
                          </div>
                      </template>
                          <template v-slot:item.date2="{ item }">
                              <div class="text-center">
                                  {{ new Date(item.date2).toLocaleDateString(prefs.Locale) }}
                              </div>
                        </template>
                        <template v-slot:item.stock="{ item }">
                        <div class="text-end">
                            <v-chip
                            :color="item.stock ? 'green' : 'red'"
                            :text="item.stock ? 'In stock' : 'Out of stock'"
                            class="text-uppercase"
                            label
                            size="small"
                            ></v-chip>
                        </div>
                        </template>
                        <template v-slot:item.approval="{ item }">
                            <div class="text-center">
                                <v-chip
                                :color="item.approval == 'Yes' ? 'green' : 'red'"
                                :text="item.approval == 'Yes' ? 'Yes' : 'No'"
                                :prepend-icon="item.approval == 'Yes' ? 'mdi-checkbox-marked-circle' : 'mdi-close'"
                                class="ma-2"
                                size="small"
                                >
                                {{item.approval}}</v-chip>
                            </div>
                        </template>
                              <template v-slot:item.status="{ item }">
                                <div class="text-center">
                                  <v-chip
                                  class="ma-2"
                                  :color="item.status ==='Completed' ?'teal': item.status ==='In-Progress' ? 'orange' : 'red'"
                                  :prepend-icon="item.status ==='Completed' ?'mdi-checkbox-marked-circle': item.status ==='In-Progress' ? 'mdi-progress-alert' : 'mdi-alert'"
                                  size="small"
                                >
                                  {{item.status}}
                                </v-chip>
                                </div>
                        </template>
                        <template v-slot:item.priority="{ item }">
                        <div class="text-end">
                            <v-chip
                            :color="item.priority ==='High' ? 'red' : item.priority ==='Medium' ? 'orange' : 'green'"
                            :text="item.priority"
                            class="text-uppercase"
                            label
                            size="small"
                            ></v-chip>
                        </div>
                        </template>
                    <template v-slot:item.actions="{ item }">
                      <v-icon
                        size="small"
                        class="me-2"
                        @click="editItem(item)"
                      >
                        mdi-pencil
                      </v-icon>
                      <v-icon
                        size="small"
                        @click="deleteItem(item)"
                        color="red"
                      >
                        mdi-delete
                      </v-icon>
                    </template>
                    <template v-slot:no-data>
                      <v-btn
                        color="primary"
                        @click="initialize"
                      >
                        Reset
                      </v-btn>
                    </template>
                  </v-data-table>
                  <v-snackbar
                        v-model="snackbar.show"
                        :color="snackbar.color"
                        :timeout="snackbar.timeout"
                        :vertical="snackbar.vertical"
                        :right="snackbar.right"
                        :bottom="snackbar.bottom"
                        multi-line
                         >
                     <strong>{{snackbar.text}}</strong>
    
                    <template v-slot:actions>
                    <v-btn
                        color="red"
                        variant="text"
                        @click="snackbar.show = false"
                    >
                        Close
                    </v-btn>
            </template>
          </v-snackbar>
            </v-app>
        </script>
</body>

</html>

例如,如果我在表单字段中输入 00:00,它将显示如下 1899-12-30T02:46:50.000Z 这是我的电子表格和应用程序脚本网络应用程序

screenshot of time format issue

我尝试了很多方法,但我几乎没有知识,所以我放弃了..

有好心人帮帮我吗?还是谢谢你

html google-apps-script google-sheets vuetify.js crud
1个回答
0
投票

这次我在编辑问题时放慢了速度,找到了时间格式问题的解决方案。

添加此功能以将时间字符串正确转换为时间对象并有效。

                            const timeFlds = this.schema.filter(
                                (fld) => fld.type === "time"
                            );
                            data = data.map((item) => {
                                timeFlds.forEach((fld) => {
                                    const dt = new Date(item[fld.key]);
                                    const hours = ("0" + dt.getHours()).slice(-2);
                                    const minutes = ("0" + dt.getMinutes()).slice(-2);
                                    item[fld.key] = `${hours}:${minutes}`;
                                });
                                return item;
                            });
© www.soinside.com 2019 - 2024. All rights reserved.