如何将复选框的状态保存到本地存储并在JavaScript待办事项列表中渲染回来?

huangapple go评论68阅读模式
英文:

how to save the checkboxes status to local storage and render it back in javascript to-do list?

问题

您提到,您正在使用基本的JavaScript制作一个待办事项列表应用程序,但在保存复选框输入元素的检查状态以及在刷新页面时重新渲染它时遇到了问题。您已经尝试通过迭代复选框来添加“checked”属性,并为每个元素添加事件侦听器以查看它们是否被选中并更改它们对应的待办事项对象的“check”属性,但在页面重新加载后,数组的“check”属性又变回了false,并且没有呈现任何已选属性。

这个问题可能是因为您的代码在页面加载时并没有将保存在localStorage中的“toDoListArray”数据重新应用到页面上。您需要在页面加载时检查localStorage中是否有保存的数据,并在有数据的情况下将其应用到页面上。

您可以尝试在页面加载时添加以下代码来解决这个问题:

window.addEventListener('load', () => {
  // 检查localStorage中是否有保存的数据
  const savedData = JSON.parse(localStorage.getItem("items"));
  
  if (savedData && savedData.toDoListArray) {
    toDoListArray = savedData.toDoListArray;
    // 然后重新渲染页面
    addItemHTML();
  }
});

将此代码添加到您的JavaScript中,以确保在页面加载时将保存的数据重新应用到待办事项列表中。这样,即使页面刷新,您保存的检查状态也会被正确呈现。

英文:

I am making a to-do list app using basic javascript. I am having a problem with saving the checking status of the checkbox input element and rendering it back when the page is refreshed... I am currently learning javascript, so my whole approach to the checkboxes might need to be changed so tell me about the best method to do so.

here's the code:

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

let toDoListArray = JSON.parse(localStorage.getItem(&quot;items&quot;)) || {
  toDoListArray: [
    {
      inputValue: &quot;wash the dishes&quot;,
      dateValue: &quot;1-1-2023&quot;,
      check: false,
    },
    {
      inputValue: &quot;checked example 2&quot;,
      dateValue: &quot;22-3-2025&quot;,
      check: true,
    },
  ],
};

addItem();

// the code i used for the checkboxes
let list = [];

document.querySelectorAll(&quot;input[type=checkbox]&quot;).forEach((element) =&gt; {
  list.push(element);
  let idx = list.indexOf(element);

  if (toDoListArray[idx].check) {
    element.setAttribute(&quot;checked&quot;, true);
  } else if (!toDoListArray[idx].check) {
    element.removeAttribute(&quot;checked&quot;);
  }

  element.addEventListener(&quot;change&quot;, () =&gt; {
    if (element.checked) {
      toDoListArray[idx].check = true;
    } else {
      toDoListArray[idx].check = false;
    }
  });
});

//end of checkboxes code


function addItem() {
  let savedText = document.querySelector(&quot;.task-input&quot;);
  let inputValue = savedText.value;
  let savedDate = document.querySelector(&quot;.date-input&quot;);
  let dateValue = savedDate.value;
  let check = false;

  if (inputValue) {
    toDoListArray.push({
      inputValue,
      dateValue,
      check,
    });
  }

  addItemHTML();

  savedText.value = &quot;&quot;;
  savedDate.value = &quot;&quot;;
}

function deleteItem(index) {
  toDoListArray.splice(index, 1);
  addItemHTML();
}

function addItemHTML() {
  let addedHTML = &quot;&quot;;

  for (let i = 0; i &lt; toDoListArray.length; i++) {
    let { inputValue, dateValue } = toDoListArray[i];
    addedHTML += `
      &lt;div class=&quot;rendered-list-item&quot;&gt;
        &lt;input id=&quot;check${i}&quot; type=&quot;checkbox&quot;&gt;
        &lt;label for=&quot;check${i}&quot;&gt;${inputValue}&lt;/label&gt;
        &lt;div&gt;${dateValue}&lt;/div&gt;
        &lt;button class=&quot;delete&quot; onclick=&quot;deleteItem(${i})&quot;) &gt;Delete&lt;/button&gt;
      &lt;/div&gt;
    `;
  }

  let jsonString = JSON.stringify(toDoListArray);
  localStorage.setItem(&quot;items&quot;, jsonString);

  document.querySelector(&quot;.list&quot;).innerHTML = addedHTML;
}

<!-- language: lang-css -->

* {
  margin: 0 auto;
  padding: 0;
  box-sizing: border-box;
  font-family: sans-serif;
}
html {
  scroll-behavior: smooth;
}

:root {
  --form-hue: 226;
  --form-saturation: 53%;
  --form-light: 90%;
  --form-bg-color: hsl(
    var(--form-hue),
    var(--form-saturation),
    var(--form-light)
  );
  --header-bg-color: rgba(147, 147, 147, 0.6);
  --header-color: aliceblue;
  --list-bg-color: rgba(201, 199, 223, 0.3);
  --main-bg-color: hsl(221, 70%, 95%);
  --add-color: white;
}

body::-webkit-scrollbar {
  width: 0.25rem;
}

body::-webkit-scrollbar-track {
  background: #c9c9d7;
}

body::-webkit-scrollbar-thumb {
  background: rgb(61, 61, 169);
}

main {
  display: flex;
  justify-content: center;
  align-items: center;
  flex-direction: column;
  background-color: var(--main-bg-color);
  width: 60%;
  height: 100%;
  padding: 20px;
}

.header,
.form,
.list {
  width: 100%;
  padding: 10px;
  margin: 10px;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
}
.header {
  border-radius: 10px;
  background-color: var(--header-bg-color);
  color: var(--header-color);
  font-weight: bold;
}

.form {
  background-color: var(--form-bg-color);
  border-radius: 10px;
}

.list {
  background-color: var(--list-bg-color);
  border-radius: 5px;
  flex-direction: column;
  width: 100%;
}

.task-input,
.date-input,
.add {
  border-radius: 10px;
  padding: 7px;
  margin: 5px;
  border: none;
  outline: none;
}

.add {
  background-color: hsl(
    var(--form-hue),
    var(--form-saturation),
    calc(var(--form-light) * 0.5)
  );
  color: var(--add-color);
  transition: 0.2s;
}

.add:hover {
  background-color: hsl(0, 0%, 71%);
  scale: 1.07;
  font-weight: bold;
  cursor: pointer;
}

.add:active {
  background-color: aliceblue;
}

.task-input:focus,
.date-input:focus {
  background-color: hsl(240, 33%, 95%);
}

.task-input:hover,
.date-input:hover {
  outline: 2px solid rgba(62, 93, 152, 0.6);
}

@media only screen and (max-width: 600px) {
  main {
    width: 100%;
  }
}

.rendered-list-item {
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-direction: row;
  background-color: hsl(0, 100%, 100%);
  border-radius: 10px;
  padding: 5px;
  margin: 5px;
  width: 95%;
  flex-wrap: wrap;
}

.list .rendered-list-item:nth-child(even) {
  background-color: hsla(222, 32%, 88%, 0.824);
}

.list .rendered-list-item:nth-child(even) div:nth-child(3) {
  color: hsla(224, 43%, 72%, 0.824);
}

.rendered-list-item:hover {
  background-color: hsla(0, 0%, 100%, 0.824);
}

.rendered-list-item label,
div,
button {
  padding: 10px;
  border-radius: 10px;
  border: none;
}

.rendered-list-item button {
  align-self: normal;
  transition: 0.2s;
  margin-right: 5px;
  color: hsl(0, 0%, 71%);
}

.rendered-list-item button:hover {
  scale: 1.08;
  background-color: hsl(0, 65%, 55%);
  color: white;
  cursor: pointer;
}

.rendered-list-item div:nth-child(3) {
  color: hsl(0, 0%, 71%);
}

.rendered-list-item label:nth-child(2) {
  background-color: hsl(233, 100%, 98%);
  margin-left: 5px;
  flex: 1;
  transition: 0.5s;
}

.rendered-list-item input[type=&quot;checkbox&quot;]:checked + label {
  font-weight: bold;
  text-decoration: line-through;
  color: hsl(0, 0%, 71%);
}

.rendered-list-item input[type=&quot;checkbox&quot;] {
  align-self: normal;
  margin-left: 5px;
  opacity: 0.6;
  accent-color: hsl(262, 25%, 56%);
  width: 0.9rem;
}

<!-- language: lang-html -->

&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
  &lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot; /&gt;
    &lt;meta http-equiv=&quot;X-UA-Compatible&quot; content=&quot;IE=edge&quot; /&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot; /&gt;
    &lt;title&gt;vanilla javascipt ToDoList&lt;/title&gt;
  &lt;/head&gt;
  &lt;body&gt;
    &lt;main&gt;
      &lt;p class=&quot;header&quot;&gt;To-Do-List&lt;/p&gt;
      &lt;div class=&quot;form&quot;&gt;
        &lt;input placeholder=&quot;type the task&quot; type=&quot;text&quot; class=&quot;task-input&quot; /&gt;
        &lt;input type=&quot;date&quot; class=&quot;date-input&quot; /&gt;
        &lt;button class=&quot;add&quot; onclick=&quot;addItem()&quot;&gt;Add&lt;/button&gt;
      &lt;/div&gt;
      &lt;div class=&quot;list&quot;&gt;&lt;/div&gt;
    &lt;/main&gt;
  &lt;/body&gt;
&lt;/html&gt;

<!-- end snippet -->

as u can see, I tried iterating through the checkboxes to add a "checked" attribute to the ones with the index that corresponds with the saved to-do-list array index and also add an event listener to each element to see if they are checked and change their corresponding to-do list object's check property, but when the page is reloaded the array's check property returns back to false and no checked attributes are rendered. when I console log the to-do list array after the event listener and I check the checkbox, the array's check attribute gets updated to true but once I refresh the page, it becomes false again.

答案1

得分: 1

似乎您在单击复选框时没有记录更改到本地存储。

element.addEventListener("change", () => {
    if (element.checked) {
        toDoListArray[idx].check = true;
    } else {
        toDoListArray[idx].check = false;
    }
});

这个事件会改变选中状态,但没有触发您的 localStorage.setItem,该操作只在 addItemHTML 中找到。

英文:

It seems to me you're not logging the change to localStorage when you click the checkbox.

element.addEventListener(&quot;change&quot;, () =&gt; {
      if (element.checked) {
        toDoListArray[idx].check = true;
      } else {
        toDoListArray[idx].check = false;
      }
    });

This event changes the checked state but there's nothing that triggers your localStorage.setItem which is only found in the addItemHTML.

答案2

得分: 1

以下是您的代码的中文翻译部分:

  1. 你的代码存在两个问题:

    问题一:根据你的代码,toDoListArray 应该类似于以下结构:

    [
      {
        inputValue: "洗碗",
        dateValue: "2023-1-1",
        check: false,
      },
      {
        inputValue: "示例2已选中",
        dateValue: "2025-3-22",
        check: true,
      },
    ]
    

    但是,在开始时,你尝试将 toDoListArray 设置为 JSON.parse(localStorage.getItem("items")),它遵循了上述的数组格式。

    并且因为你使用了 逻辑或运算符 ||,如果 JSON.parse(localStorage.getItem("items"))falsenull),那么我们将会将 toDoListArray 设置为:

    {
      toDoListArray: [
        {
          inputValue: "洗碗",
          dateValue: "2023-1-1",
          check: false,
        },
        {
          inputValue: "示例2已选中",
          dateValue: "2025-3-22",
          check: true,
        },
      ],
    }
    

    现在,如果你看到 toDoListArray 的两个值是不同的,一个是对象,另一个是数组。你可能没有注意到这一点,因为你已经在 localStorage 中保存了正确的数组格式。

    为了解决这个问题,我们可以这样做:

    let toDoListArray = JSON.parse(localStorage.getItem("items")) || [
      {
        inputValue: "洗碗",
        dateValue: "2023-1-1",
        check: false,
      },
      {
        inputValue: "示例2已选中",
        dateValue: "2025-3-22",
        check: true,
      },
    ];
    
  2. 问题二是你提到的,复选框的选中和取消选中状态在重新加载时不是持久的。

    这个问题的原因是在复选框状态改变时,你也需要更新它在 localStorage 中的状态,像这样:

    element.addEventListener("change", () => {
      if (element.checked) {
        toDoListArray[idx].check = true;
      } else {
        toDoListArray[idx].check = false;
      }
    
      localStorage.setItem("items", JSON.stringify(toDoListArray));
    });
    

最终代码:

<!-- 在这里插入你的HTML和CSS代码 -->

<script>
  let toDoListArray = JSON.parse(localStorage.getItem("items")) || [
    {
      inputValue: "洗碗",
      dateValue: "2023-1-1",
      check: false,
    },
    {
      inputValue: "示例2已选中",
      dateValue: "2025-3-22",
      check: true,
    },
  ];

  addItem();

  // 复选框代码
  let list = [];

  document.querySelectorAll("input[type=checkbox]").forEach((element) => {
    list.push(element);
    let idx = list.indexOf(element);

    if (toDoListArray[idx].check) {
      element.setAttribute("checked", true);
    } else if (!toDoListArray[idx].check) {
      element.removeAttribute("checked");
    }

    element.addEventListener("change", () => {
      if (element.checked) {
        toDoListArray[idx].check = true;
      } else {
        toDoListArray[idx].check = false;
      }

      localStorage.setItem("items", JSON.stringify(toDoListArray));
    });
  });

  // 结束复选框代码

  function addItem() {
    let savedText = document.querySelector(".task-input");
    let inputValue = savedText.value;
    let savedDate = document.querySelector(".date-input");
    let dateValue = savedDate.value;
    let check = false;

    if (inputValue) {
      toDoListArray.push({
        inputValue,
        dateValue,
        check,
      });
    }

    addItemHTML();

    savedText.value = "";
    savedDate.value = "";
  }

  function deleteItem(index) {
    toDoListArray.splice(index, 1);
    addItemHTML();
  }

  function addItemHTML() {
    let addedHTML = "";

    for (let i = 0; i < toDoListArray.length; i++) {
      let { inputValue, dateValue } = toDoListArray[i];
      addedHTML += `
        <div class="rendered-list-item">
          <input id="check${i}" type="checkbox">
          <label for="check${i}">${inputValue}</label>
          <div>${dateValue}</div>
          <button class="delete" onclick="deleteItem(${i})">删除</button>
        </div>
      `;
    }

    localStorage.setItem("items", JSON.stringify(toDoListArray));

    document.querySelector(".list").innerHTML = addedHTML;
  }
</script>

希望这有助于你解决代码中的问题!

英文:

There are two issues with your code:

  1. As per your code toDoListArray should look something like this:

    [
      {
        inputValue: &quot;wash the dishes&quot;,
        dateValue: &quot;1-1-2023&quot;,
        check: false,
      },
      {
        inputValue: &quot;checked example 2&quot;,
        dateValue: &quot;22-3-2025&quot;,
        check: true,
      },
    ]
    

    But, in the beginning, you are trying to set toDoListArray as JSON.parse(localStorage.getItem(&quot;items&quot;)) which follows the above array format.

    And because you using logical OR operator || if JSON.parse(localStorage.getItem(&quot;items&quot;)) is false (null) then we will set the toDoListArray as

    {
      toDoListArray: [
        {
          inputValue: &quot;wash the dishes&quot;,
          dateValue: &quot;1-1-2023&quot;,
          check: false,
        },
        {
          inputValue: &quot;checked example 2&quot;,
          dateValue: &quot;22-3-2025&quot;,
          check: true,
        },
      ],
    }
    

    Now if you see both values of toDoListArray are diffrent as one is a object and other is an array.
    You might have not noticed this as you already have the correct array format save in the localStorage.

    To fix this we can just this:

    let toDoListArray = JSON.parse(localStorage.getItem(&quot;items&quot;)) || [
      {
        inputValue: &quot;wash the dishes&quot;,
        dateValue: &quot;1-1-2023&quot;,
        check: false,
      },
      {
        inputValue: &quot;checked example 2&quot;,
        dateValue: &quot;22-3-2025&quot;,
        check: true,
      },
    ];
    

<br />

  1. The second issue is what you have mentioned, that the check and unchecked state of the checkbox is not persistent on reload.

    The reason for this is that on change of the checkbox state, you also need to update it in the localStorage. Like this:

    element.addEventListener(&quot;change&quot;, () =&gt; {
      if (element.checked) {
        toDoListArray[idx].check = true;
      } else {
        toDoListArray[idx].check = false;
      }
    
      localStorage.setItem(&quot;items&quot;, JSON.stringify(toDoListArray));
    });
    

<br />

Final Code:

<!-- begin snippet: js hide: true console: true babel: false -->

<!-- language: lang-js -->

let toDoListArray = JSON.parse(localStorage.getItem(&quot;items&quot;)) || [{
inputValue: &quot;wash the dishes&quot;,
dateValue: &quot;1-1-2023&quot;,
check: false,
},
{
inputValue: &quot;checked example 2&quot;,
dateValue: &quot;22-3-2025&quot;,
check: true,
},
];
addItem();
// the code i used for the checkboxes
let list = [];
document.querySelectorAll(&quot;input[type=checkbox]&quot;).forEach((element) =&gt; {
list.push(element);
let idx = list.indexOf(element);
if (toDoListArray[idx].check) {
element.setAttribute(&quot;checked&quot;, true);
} else if (!toDoListArray[idx].check) {
element.removeAttribute(&quot;checked&quot;);
}
element.addEventListener(&quot;change&quot;, () =&gt; {
if (element.checked) {
toDoListArray[idx].check = true;
} else {
toDoListArray[idx].check = false;
}
localStorage.setItem(&quot;items&quot;, JSON.stringify(toDoListArray));
});
});
//end of checkboxes code
function addItem() {
let savedText = document.querySelector(&quot;.task-input&quot;);
let inputValue = savedText.value;
let savedDate = document.querySelector(&quot;.date-input&quot;);
let dateValue = savedDate.value;
let check = false;
if (inputValue) {
toDoListArray.push({
inputValue,
dateValue,
check,
});
}
addItemHTML();
savedText.value = &quot;&quot;;
savedDate.value = &quot;&quot;;
}
function deleteItem(index) {
toDoListArray.splice(index, 1);
addItemHTML();
}
function addItemHTML() {
let addedHTML = &quot;&quot;;
for (let i = 0; i &lt; toDoListArray.length; i++) {
let {
inputValue,
dateValue
} = toDoListArray[i];
addedHTML += `
&lt;div class=&quot;rendered-list-item&quot;&gt;
&lt;input id=&quot;check${i}&quot; type=&quot;checkbox&quot;&gt;
&lt;label for=&quot;check${i}&quot;&gt;${inputValue}&lt;/label&gt;
&lt;div&gt;${dateValue}&lt;/div&gt;
&lt;button class=&quot;delete&quot; onclick=&quot;deleteItem(${i})&quot;) &gt;Delete&lt;/button&gt;
&lt;/div&gt;
`;
}
localStorage.setItem(&quot;items&quot;, JSON.stringify(toDoListArray));
document.querySelector(&quot;.list&quot;).innerHTML = addedHTML;
}

<!-- language: lang-css -->

* {
margin: 0 auto;
padding: 0;
box-sizing: border-box;
font-family: sans-serif;
}
html {
scroll-behavior: smooth;
}
:root {
--form-hue: 226;
--form-saturation: 53%;
--form-light: 90%;
--form-bg-color: hsl( var(--form-hue), var(--form-saturation), var(--form-light));
--header-bg-color: rgba(147, 147, 147, 0.6);
--header-color: aliceblue;
--list-bg-color: rgba(201, 199, 223, 0.3);
--main-bg-color: hsl(221, 70%, 95%);
--add-color: white;
}
body::-webkit-scrollbar {
width: 0.25rem;
}
body::-webkit-scrollbar-track {
background: #c9c9d7;
}
body::-webkit-scrollbar-thumb {
background: rgb(61, 61, 169);
}
main {
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
background-color: var(--main-bg-color);
width: 60%;
height: 100%;
padding: 20px;
}
.header,
.form,
.list {
width: 100%;
padding: 10px;
margin: 10px;
display: flex;
flex-wrap: wrap;
justify-content: center;
align-items: center;
}
.header {
border-radius: 10px;
background-color: var(--header-bg-color);
color: var(--header-color);
font-weight: bold;
}
.form {
background-color: var(--form-bg-color);
border-radius: 10px;
}
.list {
background-color: var(--list-bg-color);
border-radius: 5px;
flex-direction: column;
width: 100%;
}
.task-input,
.date-input,
.add {
border-radius: 10px;
padding: 7px;
margin: 5px;
border: none;
outline: none;
}
.add {
background-color: hsl( var(--form-hue), var(--form-saturation), calc(var(--form-light) * 0.5));
color: var(--add-color);
transition: 0.2s;
}
.add:hover {
background-color: hsl(0, 0%, 71%);
scale: 1.07;
font-weight: bold;
cursor: pointer;
}
.add:active {
background-color: aliceblue;
}
.task-input:focus,
.date-input:focus {
background-color: hsl(240, 33%, 95%);
}
.task-input:hover,
.date-input:hover {
outline: 2px solid rgba(62, 93, 152, 0.6);
}
@media only screen and (max-width: 600px) {
main {
width: 100%;
}
}
.rendered-list-item {
display: flex;
justify-content: space-between;
align-items: center;
flex-direction: row;
background-color: hsl(0, 100%, 100%);
border-radius: 10px;
padding: 5px;
margin: 5px;
width: 95%;
flex-wrap: wrap;
}
.list .rendered-list-item:nth-child(even) {
background-color: hsla(222, 32%, 88%, 0.824);
}
.list .rendered-list-item:nth-child(even) div:nth-child(3) {
color: hsla(224, 43%, 72%, 0.824);
}
.rendered-list-item:hover {
background-color: hsla(0, 0%, 100%, 0.824);
}
.rendered-list-item label,
div,
button {
padding: 10px;
border-radius: 10px;
border: none;
}
.rendered-list-item button {
align-self: normal;
transition: 0.2s;
margin-right: 5px;
color: hsl(0, 0%, 71%);
}
.rendered-list-item button:hover {
scale: 1.08;
background-color: hsl(0, 65%, 55%);
color: white;
cursor: pointer;
}
.rendered-list-item div:nth-child(3) {
color: hsl(0, 0%, 71%);
}
.rendered-list-item label:nth-child(2) {
background-color: hsl(233, 100%, 98%);
margin-left: 5px;
flex: 1;
transition: 0.5s;
}
.rendered-list-item input[type=&quot;checkbox&quot;]:checked+label {
font-weight: bold;
text-decoration: line-through;
color: hsl(0, 0%, 71%);
}
.rendered-list-item input[type=&quot;checkbox&quot;] {
align-self: normal;
margin-left: 5px;
opacity: 0.6;
accent-color: hsl(262, 25%, 56%);
width: 0.9rem;
}

<!-- language: lang-html -->

&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
  &lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot; /&gt;
    &lt;meta http-equiv=&quot;X-UA-Compatible&quot; content=&quot;IE=edge&quot; /&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot; /&gt;
    &lt;title&gt;vanilla javascipt ToDoList&lt;/title&gt;
  &lt;/head&gt;
  &lt;body&gt;
    &lt;main&gt;
      &lt;p class=&quot;header&quot;&gt;To-Do-List&lt;/p&gt;
      &lt;div class=&quot;form&quot;&gt;
        &lt;input placeholder=&quot;type the task&quot; type=&quot;text&quot; class=&quot;task-input&quot; /&gt;
        &lt;input type=&quot;date&quot; class=&quot;date-input&quot; /&gt;
        &lt;button class=&quot;add&quot; onclick=&quot;addItem()&quot;&gt;Add&lt;/button&gt;
      &lt;/div&gt;
      &lt;div class=&quot;list&quot;&gt;&lt;/div&gt;
    &lt;/main&gt;
  &lt;/body&gt;
&lt;/html&gt;

<!-- end snippet -->

huangapple
  • 本文由 发表于 2023年6月9日 01:43:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/76434444.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定