ExtJS做的一個信息管理界面

前段時間公司讓我們學習ExtJS,學習了一個禮拜,完成了個小練習,思來想去決定做個總結,但是又懶得敲word,於是就在代碼上每行都加上註釋,以後忘記了就翻開來看看。

在這裏給出代碼。

完成的功能如圖所示。

Js代碼 收藏代碼
  1. /**
  2. *默認頁面
  3. *
  4. *@authorleaves.qq:1330771552
  5. */
  6. Ext.define('SupplyManagementDesktop.defaultsWindow',{
  7. extend:'Ext.ux.desktop.Module',
  8. requires:['Ext.data.ArrayStore','Ext.util.Format','Ext.grid.Panel',
  9. 'Ext.grid.RowNumberer','Ext.ux.LiveSearchGridPanel'],
  10. id:'defaultsWindow-win',
  11. /***************************************************************************
  12. *ExtJS控件使用按照如下規則。首先,創建控件,調用Ext.create
  13. *weightName:空間命名空間,args:空間參數,用{}包圍,當做對象傳入
  14. *
  15. *#######################################注意JS中有如下語法:varobject={
  16. *paramter1:value1,paramter2:value2,paramter3:value3}
  17. *object.paramter1可以直接獲得value1#####################################
  18. *
  19. *ExtJS中所有空間創建方法都如上
  20. *
  21. *Ext.create(StringweightName,Mixedargs)
  22. *所以此處args相當於一個匿名對象(沒有引用),但並非真的匿名對象
  23. *
  24. */
  25. //初始化窗體的方法
  26. init:function(){
  27. this.launcher={
  28. text:'DefaultsWindow',
  29. iconCls:'icon-grid',
  30. //調用createWindow方法
  31. handler:this.createWindow,
  32. scope:this
  33. //this指向Ext.define(這個方法用來聲明命名空間。)定義的命名空間
  34. };
  35. },//初始化窗體的方法結束
  36. //創建窗體的方法
  37. createWindow:function(){
  38. //下面進行預定義。就好像C裏面的先定義後使用。不然後定義的在前面使用會認爲未初始化。(猜測:可能不跟JS一樣,屬於ExtJS的語法)
  39. vardataPanel;//預定義一個GridPanel,用來顯示數據
  40. varinnerPanel;//存放Panel的容器
  41. varworkerPanel;
  42. varwestPanel;
  43. vardeptStore;
  44. varmoduleObj=this;//創建windows窗體的時獲取下本身的環境,此處不能確定,這個this是指向Ext.define還是指向創建的這個窗體
  45. vardesktop=this.app.getDesktop();
  46. //獲取窗體,外部最大窗體,具體方法不清楚。
  47. varwin=desktop.getWindow('defaultsWindow-win');
  48. //創建按鈕bar組件,是上面的幾個按鈕。
  49. varbuttonBar=Ext.create('Ext.toolbar.Toolbar',{
  50. dock:'top',
  51. items:[{
  52. xtype:'button',
  53. text:'新建',
  54. iconCls:'add',
  55. handler:function(){
  56. //自行新建操作,傳入一個create字符串用來標示是什麼按鈕事件,傳入dataPanel(注意:上面沒有var
  57. //dataPanel;此處會報錯。)因爲後面的新建需要用到表格顯示的數據(dataPanel.getSelectionModel().getSelection())
  58. moduleObj.proAction("create",dataPanel,
  59. workerPanel);
  60. }
  61. },{
  62. //分隔符,不解釋。
  63. xtype:'tbseparator'
  64. },{
  65. xtype:'button',
  66. text:'刪除',
  67. iconCls:'remove',
  68. handler:function(){
  69. moduleObj.proAction("delete",dataPanel);
  70. }
  71. },{
  72. xtype:'tbseparator'
  73. },{
  74. xtype:'button',
  75. text:'複製',
  76. iconCls:'copy',
  77. handler:function(){
  78. moduleObj.proAction("copy",dataPanel,workerPanel);
  79. }
  80. },{
  81. xtype:'button',
  82. text:'重置檢索',
  83. iconCls:'reset',
  84. handler:function(){
  85. dataPanel.resetSearch();
  86. }
  87. }]
  88. });//創建按鈕bar組件結束
  89. //臨時創建的一個用來展示的store
  90. vartheStore=Ext.create('Ext.data.Store',{
  91. fields:[{
  92. name:'projectId',
  93. type:'String'
  94. },{
  95. name:'projectCode',
  96. type:'String'
  97. },{
  98. name:'projectName',
  99. type:'String'
  100. },{
  101. name:'startDate',
  102. type:'String'
  103. },{
  104. name:'endDate',
  105. type:'string'
  106. },{
  107. name:'qualityTarget',
  108. type:'string'
  109. },{
  110. name:'projectLeader',
  111. type:'string'
  112. },{
  113. name:'projectStatus',
  114. type:'string'
  115. },{
  116. name:'qualification',
  117. type:'string'
  118. },{
  119. name:'constructionUnit',
  120. type:'string'
  121. }],
  122. pageSize:20,//每頁顯示數量。此處設置可以在向後臺申請數據的時候“自動”傳參一個
  123. //limit和satrt,start不需要指定ExtJS會自動計算,然後傳值。
  124. proxy:{
  125. type:'ajax',//使用傳輸方式爲ajax(ajax是異步執行的操作,即不需要刷新頁面即可申請後臺資源。)
  126. method:'POST',//post和get是HTML中表單(form)提交兩種方式,get會在地址欄顯示參數,post不顯示
  127. url:'/Training/myProjectInfoController/getAllProjectInfo.action?deptId='
  128. +0,
  129. reader:{//設置讀取方式屬性
  130. type:'json',//設置讀取方式格式爲:json字符串
  131. root:'root',//設置根元素,即讀取上面fields種的name中對應值的元素,此處多爲元素組,json字符串如:{A:a,B:[{},{},{},………………]}
  132. totalProperty:'totalProperty'//設置總頁碼
  133. }
  134. },
  135. autoLoad:true
  136. //自動讀取,即顯示綁定該store的組件的時候直接讀取數據
  137. });
  138. //創建臨時Store結束
  139. //創建分頁bar組建
  140. varpagebar=Ext.create('Ext.toolbar.Paging',{
  141. pageSize:20,
  142. store:theStore,
  143. dock:'bottom',
  144. setActive:false,
  145. refresh:false,
  146. displayInfo:true,
  147. plugins:Ext.create('Ext.ux.ProgressBarPager',{})
  148. });
  149. //創建分頁bar組建結束
  150. //爲theGirdPanel創建一個SelectionModel
  151. varselectionModeltoGridPanel=Ext
  152. .create('Ext.selection.CheckboxModel');//想要能進行選擇或者多選,就需要設置selModel屬性這是設置selection的模型,創建一個模型Ext.selection.CheckboxModel
  153. //初始化gridPanel
  154. dataPanel=Ext.create('Ext.ux.LiveSearchGridPanel',{
  155. title:'<fontcolor=red>工程詳細信息</font>',
  156. region:'center',
  157. width:'100%',
  158. height:'96%',
  159. store:theStore,
  160. selModel:selectionModeltoGridPanel,
  161. //一系列行,不解釋,也可以varcolumn=[`````````]然後columns:column
  162. iconCls:'remove',
  163. columns:[{
  164. dataIndex:'projectId',
  165. width:80,
  166. text:'項目號'
  167. },{
  168. dataIndex:'projectCode',
  169. width:80,
  170. text:'項目序號'
  171. },{
  172. dataIndex:'projectName',
  173. width:100,
  174. text:'項目名稱'
  175. },{
  176. dataIndex:'constructionUnit',
  177. width:100,
  178. text:'建設單位'
  179. },{
  180. dataIndex:'startDate',
  181. width:80,
  182. text:'開工日期'
  183. },{
  184. dataIndex:'endDate',
  185. width:80,
  186. text:'竣工日期'
  187. },{
  188. dataIndex:'qualityTarget',
  189. width:100,
  190. text:'質量目標'
  191. },{
  192. dataIndex:'projectLeader',
  193. width:100,
  194. text:'項目負責人'
  195. },{
  196. dataIndex:'projectStatus',
  197. width:80,
  198. text:'項目狀態'
  199. },{
  200. dataIndex:'qualification',
  201. width:80,
  202. text:'需要資質'
  203. }],
  204. dockedItems:[buttonBar,pagebar]
  205. });
  206. //綁定dataPanel鼠標雙擊事件。
  207. dataPanel.on('itemdblclick',function(){
  208. moduleObj.proAction("update",dataPanel,workerPanel);
  209. });
  210. //初始化gridPanel結束
  211. //爲下面的部門信息分類欄(grid)創建一個store數據用jsonu讀取/Training/DeptInfoController/getAllDeptInfo.action地址申請到的資源。
  212. deptStore=Ext.create('Ext.data.Store',{
  213. fields:[{
  214. name:'deptId',
  215. type:'String'
  216. },{
  217. name:'deptName',
  218. type:'String'
  219. }],
  220. proxy:{
  221. type:'ajax',
  222. method:'POST',
  223. url:'/Training/DeptInfoController/getAllDeptInfo.action',
  224. reader:{
  225. type:'json',//用json字符串
  226. root:'root'
  227. }
  228. },
  229. autoLoad:true
  230. });
  231. //創建部門信息分類欄,
  232. workerPanel=Ext.create('Ext.grid.Panel',{
  233. title:'部門信息',
  234. border:false,
  235. store:deptStore,
  236. hideHeaders:true,
  237. columns:[{
  238. dataIndex:'deptId',
  239. hidden:true,
  240. sortable:false,
  241. width:180
  242. },{
  243. dataIndex:'deptName',
  244. sortable:false,
  245. width:180
  246. }]
  247. });
  248. //給部門信息的grid綁定事件,當單擊的時候觸發事件,此事件用來刷新右側列表
  249. workerPanel.on('itemclick',function(grid,record){
  250. //獲取當前行的deptId列的值
  251. varid=record.data.deptId;
  252. //dataPanel.store:獲取dataPanel的store屬性的值,dataPanel.store.proxy獲取數據來源屬性,ataPanel.store.proxy.url獲取數據來源屬性的URL,
  253. //這個方法用來重新設置數據來源的地址,
  254. //注意:後面的?deptId是HTML傳參方法,地址欄傳參。跟form直接傳參一樣,後臺可以接受。
  255. dataPanel.store.proxy.url='/Training/myProjectInfoController/getAllProjectInfo.action?deptId='
  256. +id;
  257. dataPanel
  258. .setTitle("<fontcolor=red>"
  259. +(workerPanel.getSelectionModel().getSelection())[0].data.deptName
  260. +"</font>部門信息");//ExtJS中的標題等字符串屬性支持HTML語言,直接設置格式。
  261. dataPanel.store.load();//dataPanel.store:獲取dataPanel的store屬性的值,dataPanel.store.load():調用取得的值的load()方法,用來重新加載store數據,實現grid刷新
  262. });
  263. //初始工人信息Panel,同下
  264. workerPane2=Ext.create('Ext.grid.Panel',{//Ext.grid.Panel可以直接顯示grid的panel不需要create一個Grid放置panel中
  265. title:'BBBBBB',//隨便取標題
  266. border:false,//沒有邊框
  267. store:theStore,
  268. hideHeaders:true,
  269. columns:[{
  270. dataIndex:'projectName',
  271. sortable:false,//不能排序
  272. width:180
  273. }]
  274. });
  275. //初始工人信息Panel,用來實現摺疊效果的panel
  276. workerPanel3=Ext.create('Ext.grid.Panel',{//Ext.grid.Panel可以直接顯示grid的panel不需要create一個Grid放置panel中
  277. title:'CCCCCCC',//隨便取標題
  278. border:false,//沒有邊框
  279. store:theStore,
  280. hideHeaders:true,//隱藏grid每列數據的標題
  281. columns:[{
  282. dataIndex:'projectName',
  283. sortable:false,//不能排序
  284. width:180
  285. }]
  286. });
  287. //左邊伸縮欄
  288. westPanel=Ext.create("Ext.panel.Panel",{
  289. collapsible:true,//這個屬性設置此panel容易可以隱藏(最小化)
  290. title:'分類查看',
  291. layout:'accordion',//這個屬性設置此panel容易可以實現摺疊效果
  292. width:200,
  293. region:'west',
  294. iconCls:'reset',
  295. items:[workerPanel,workerPane2,workerPanel3]
  296. //放置三個小panel容器,如上定義
  297. });
  298. //創建容器,用來存放整個窗體的組件,並且在下面直接放置到win中。
  299. theContainer=Ext.create('Ext.container.Container',{
  300. layout:'border',
  301. items:[dataPanel,westPanel]
  302. });
  303. //判斷是否已經創建最外邊窗體,如果創建了,(JS是弱類型語言,認爲null相當於false)
  304. if(!win){
  305. win=desktop.createWindow({//所以此處的目的是:如果win已經初始化存在了,那麼就不新創建窗體,直接調用下面的show()方法
  306. //下面屬性不具體解釋,詳細可以查看API手冊
  307. id:'defaultsWindow-win',
  308. title:'工程詳細信息設置',
  309. width:1100,
  310. height:600,
  311. iconCls:'icon-grid',
  312. animCollapse:false,
  313. constrainHeader:true,
  314. layout:'fit',
  315. items:[theContainer]
  316. //把創建好存放所有組件的窗體放置到外圍窗體中
  317. });
  318. }
  319. win.show();//顯示窗體。
  320. returnwin;//把窗體的句柄(相當於內存引用)返回
  321. },
  322. //創建窗體的方法結束
  323. //顯示一個對話框的方法,暫時帶有一個用來判斷是什麼按鈕的屬性
  324. proAction:function(btn,dataPanel,workerPanel){
  325. varselectData;//預設一個用來存放被選中的數據的變量
  326. varinnerPanel;
  327. //如果選擇的是複製
  328. if("copy"==btn){
  329. if(dataPanel.getSelectionModel().getSelection().length==0){
  330. Ext.hx.msg("提示","請先選擇您要複製的行");
  331. return;
  332. }
  333. selectData=(dataPanel.getSelectionModel().getSelection())[dataPanel
  334. .getSelectionModel().getCount()
  335. -1].data;//如果是刪除的話需要讀取被選中的數據,就初始化被selectData。
  336. }
  337. //如果選擇的是新建
  338. if("create"==btn){
  339. //新建的時候設置選擇的行爲null,沒有值。也就不會在創建的panel中顯示當前行。此處是因爲在複製的時候會去讀取。
  340. selectData=null;
  341. }
  342. //如果選擇的是複製
  343. if("update"==btn){
  344. selectData=(dataPanel.getSelectionModel().getSelection())[0].data;//先取出所有的記錄組成的數組。
  345. }
  346. //如果選擇的是刪除
  347. if("delete"==btn){
  348. varoneDate;//預設一個用來存放一條數據進行操作的變量
  349. varrecords=dataPanel.getSelectionModel().getSelection();//先取出所有的記錄組成的數組。
  350. //判斷如果還沒有選擇任何行就提示並且返回方法
  351. if(records.length==0){
  352. Ext.hx.msg("提示","請先選擇您要刪除的行");
  353. return;
  354. }
  355. //遍歷所有的數組然後設置裏面的各種標誌
  356. vararray=newArray();//預設一個用來存放新的data的數組
  357. for(vari=0;i<records.length;i++){
  358. oneDate=records[i].data;//取出其中一條
  359. oneDate.deleteFlg=true;//設置刪除標誌
  360. array.push(oneDate);//放置到數組中
  361. }
  362. //用ajax來進行後臺交互
  363. Ext.Ajax.request({
  364. url:'/Training/myProjectInfoController/deleteProjectInfo.action',
  365. method:'POST',
  366. success:function(res,opts){//交互成功的時候
  367. Ext.hx.msg("提示",'刪除成功!');//提示
  368. dataPanel.store.load();//表格數據刷新
  369. },
  370. failure:function(res,opts){
  371. Ext.hx.msg("提示",'刪除失敗!');
  372. },
  373. params:{
  374. jsonString:Ext.JSON.encode(array)
  375. //調用ExtJS內置對象的方法,把數組轉換成json字符串
  376. },
  377. scope:this
  378. //作用範圍本頁。//具體不知道,沒用。、
  379. });
  380. return;//執行完成操作馬上返回,不執行下面代碼。
  381. }
  382. /*下面定義一系列用來輸入的文本框*/
  383. deptBoxStore=Ext.create('Ext.data.Store',{
  384. fields:[{
  385. name:'deptId',
  386. type:'String'
  387. },{
  388. name:'deptName',
  389. type:'String'
  390. }],
  391. proxy:{
  392. type:'ajax',
  393. method:'POST',
  394. url:'/Training/DeptInfoController/getAllDeptInfo.action',
  395. reader:{
  396. type:'json',//用json字符串
  397. root:'root'
  398. }
  399. },
  400. autoLoad:true
  401. });
  402. //下面是一個下來選擇菜單,用來下拉選擇部門。
  403. vardptBox=Ext.create("Ext.form.field.ComboBox",{
  404. fieldLabel:'部門選擇',
  405. store:deptBoxStore,
  406. displayField:'deptName',
  407. valueField:'deptId',
  408. allowBlank:false,//不允許爲空
  409. editable:false,//不允許編輯
  410. x:10,
  411. y:20
  412. });
  413. //設置上面部門選擇的Combox默認值
  414. deptBoxStore.load({
  415. callback:function(records){
  416. dptBox.setValue(workerPanel.getSelectionModel().getSelection().length==0?null:(workerPanel.getSelectionModel().getSelection())[0].data.deptId);
  417. }
  418. });
  419. //各種輸入框,制定value(默認值)在沒有selectData是null(即if("create"==
  420. //btn)的時候)設置爲“”(空字符串),否則分別取出選擇行的每一個數據。作爲默認數據,
  421. varprojectIdField=Ext.create('Ext.form.field.Text',{
  422. fieldLabel:'項目號',
  423. x:10,
  424. y:20,
  425. value:selectData!=null?selectData.projectId:""
  426. });
  427. varprojectCodeField=Ext.create('Ext.form.field.Text',{
  428. fieldLabel:'項目序號',
  429. x:10,
  430. y:50,
  431. value:selectData!=null?selectData.projectCode:""
  432. });
  433. varprojectNameField=Ext.create('Ext.form.field.Text',{
  434. fieldLabel:'項目名稱',
  435. allowBlank:false,
  436. blankText:'不可以爲空',
  437. x:10,
  438. y:80,
  439. value:selectData!=null?selectData.projectName:""
  440. });
  441. varconstructionUnitField=Ext.create('Ext.form.field.Text',{
  442. fieldLabel:'建設單位',
  443. x:10,
  444. y:110,
  445. value:selectData!=null
  446. ?selectData.constructionUnit
  447. :""
  448. });
  449. varstartDateField=Ext.create('Ext.form.field.Date',{
  450. format:'Y-m-dh:m:s',
  451. fieldLabel:'開工日期',
  452. blankText:'不可以爲空',
  453. allowBlank:false,
  454. x:10,
  455. y:140,
  456. value:selectData!=null
  457. ?selectData.startDate
  458. :newDate()
  459. });
  460. varendDateField=Ext.create('Ext.form.field.Date',{
  461. format:'Y-m-dh:m:s',
  462. fieldLabel:'竣工日期',
  463. blankText:'不可以爲空',
  464. allowBlank:false,
  465. x:10,
  466. y:170,
  467. value:selectData!=null
  468. ?selectData.endDate
  469. :newDate()
  470. });
  471. varqualityTargetField=Ext.create('Ext.form.field.Text',{
  472. fieldLabel:'質量目標',
  473. x:10,
  474. y:200,
  475. value:selectData!=null?selectData.qualityTarget:""
  476. });
  477. varprojectLeaderField=Ext.create('Ext.form.field.Text',{
  478. fieldLabel:'項目負責人',
  479. x:10,
  480. y:230,
  481. value:selectData!=null?selectData.projectLeader:""
  482. });
  483. varprojectStatusField=Ext.create('Ext.form.field.Text',{
  484. fieldLabel:'項目狀態',
  485. x:10,
  486. y:260,
  487. value:selectData!=null?selectData.projectStatus:""
  488. });
  489. varqualificationField=Ext.create('Ext.form.field.Text',{
  490. fieldLabel:'需要資質',
  491. x:10,
  492. y:290,
  493. value:selectData!=null?selectData.projectStatus:""
  494. });
  495. varsubmitButton=Ext.create('Ext.button.Button',{
  496. text:'確定',
  497. x:10,
  498. y:320,
  499. value:selectData!=null?selectData.projectStatus:"",
  500. handler:function(){
  501. vararr=newArray();
  502. //上面說道的JS的定義對象的方法,
  503. /**
  504. *#######################################注意JS中有如下語法:var
  505. *object={paramter1:value1,paramter2:value2,paramter3:value3}
  506. *object.paramter1可以直接獲得value1
  507. *#####################################
  508. */
  509. vardata={
  510. projectId:projectIdField.getValue(),
  511. projectCode:projectCodeField.getValue(),
  512. projectName:projectNameField.getValue(),
  513. constructionUnit:constructionUnitField.getValue(),
  514. startDate:startDateField.getValue(),
  515. endDate:endDateField.getValue(),
  516. qualityTarget:qualityTargetField.getValue(),
  517. projectLeader:projectLeaderField.getValue(),
  518. projectStatus:projectStatusField.getValue(),
  519. qualification:qualificationField.getValue(),
  520. deptId:dptBox.getValue(),
  521. modifyFlg:"update"==btn?true:false
  522. };
  523. //上面定義的data有了projectId,projectCode,······deptId,modifyFlg這些屬性,可以直接data.modifyFlg取得值。
  524. if(!confirm("確定?")){//confirm("確定?")彈出對話框,顯示確定?點擊是的時候返回true,此處判斷如果端機否,直接返回方法不執行下面語句。
  525. return;
  526. }
  527. arr.push(data);//把設置好屬性的data對象放置到arr數組中。
  528. //用AJAX跟後臺交互。
  529. Ext.Ajax.request({
  530. url:'/Training/myProjectInfoController/saveProjectInfo.action',
  531. params:{
  532. jsonString:Ext.JSON.encode(arr)
  533. },
  534. success:function(response){
  535. Ext.hx.msg("提示","成功");
  536. vardialog=Ext.getCmp('theDialog');//Ext.getCmp(String
  537. //comID);傳入組件ID,返回組件句柄(內存引用)
  538. dataPanel.store.load();//刷新panel不解釋
  539. dialog.close();//把窗體關閉(不顯示)
  540. dialog.destroy();//把窗體銷燬(清空內存)
  541. },
  542. failure:function(response){//失敗提示
  543. Ext.hx.msg("提示","失敗");
  544. }
  545. });
  546. }
  547. });
  548. varresetButton=Ext.create('Ext.button.Button',{
  549. text:'重置',
  550. x:70,
  551. y:320,
  552. value:selectData!=null?selectData.projectStatus:"",
  553. handler:function(){
  554. /*
  555. *API上抄來的,不知道什麼意思。up(Stringselector):Container
  556. *WalksuptheownerCtaxislookingforanancestor
  557. *Containerwhichmatchesthepassedsimpleselector.
  558. */
  559. this.up('form').getForm().reset();//查找form上面的form(記住這麼用吧,說不清楚。仔細看
  560. //innerPanel=
  561. //Ext.create('Ext.form.Panel',
  562. //{
  563. //這句就知道了。)向上找form元素獲取form表單,然後重置
  564. }
  565. });
  566. //創建用來進行輸入的文本框數組
  567. /**
  568. *此處使用的是Ext.form.Panel目的是爲了上面的this.up('form').getForm().reset();
  569. */
  570. innerPanel=Ext.create('Ext.form.Panel',{//創建一個表單控件,
  571. id:'innerPanel',
  572. height:"100%",
  573. width:"100%",
  574. layout:{
  575. type:'absolute'
  576. },
  577. id:'innerPanel',
  578. waitMsgTarget:true,//顯示錯誤提示的小歎號
  579. fieldDefaults:{
  580. labelWidth:85,
  581. msgTarget:'side'//錯誤提示的字體
  582. },
  583. items:[dptBox,projectCodeField,projectNameField,
  584. constructionUnitField,startDateField,endDateField,
  585. qualityTargetField,projectLeaderField,projectStatusField,
  586. qualificationField,submitButton,resetButton]
  587. });
  588. //準備好一個用來顯示窗體的dialog,實際上是一個窗體
  589. vardlalog=Ext.create('Ext.window.Window',{
  590. id:'theDialog',
  591. title:'要點擊之後顯示的窗體',
  592. height:500,
  593. width:300,
  594. layout:'fit',
  595. items:[innerPanel],
  596. modal:true
  597. //模態窗體,顯示的時候不允許操作後面的控件。
  598. });
  599. dlalog.show();
  600. }
  601. //顯示一個對話框的方法結束
  602. });


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章