You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

showinfo.tmpl 22 kB

3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488
  1. {{template "base/head" .}}
  2. <div class="repository">
  3. {{template "repo/header" .}}
  4. <style>
  5. .model_header_text{
  6. font-size: 14px;
  7. color: #101010;
  8. font-weight: bold;
  9. }
  10. .ti_form{
  11. text-align: left;
  12. max-width: 100%;
  13. vertical-align: middle;
  14. }
  15. .ti-text-form-label {
  16. padding-bottom: 20px;
  17. padding-right: 20px;
  18. color: #8a8e99;
  19. font-size: 14px;
  20. white-space: nowrap !important;
  21. width: 80px;
  22. line-height: 30px;
  23. }
  24. .ti-text-form-content {
  25. line-height: 30px;
  26. padding-bottom: 20px;
  27. width: 100%;
  28. }
  29. .change-version{
  30. min-width: auto !important;
  31. border: 1px solid rgba(187, 187, 187, 100) !important;
  32. border-radius: .38571429rem !important;
  33. margin-left: 1.5em;
  34. }
  35. .title-word-elipsis{
  36. overflow: hidden;
  37. text-overflow: ellipsis;
  38. white-space: nowrap;
  39. width: 30%;
  40. }
  41. .word-elipsis{
  42. overflow: hidden;
  43. text-overflow: ellipsis;
  44. white-space: nowrap;
  45. padding-right: 80px;
  46. }
  47. .half-table{
  48. width: 50%;
  49. float: left;
  50. }
  51. .text-width80 {
  52. width: 100px;
  53. line-height: 30px;
  54. }
  55. .tableStyle{
  56. width:100%;
  57. table-layout: fixed;
  58. }
  59. .iword-elipsis{
  60. display: inline-block;
  61. width: 80%;
  62. overflow: hidden;
  63. text-overflow: ellipsis;
  64. white-space: nowrap;
  65. }
  66. </style>
  67. <div class="ui container">
  68. <h4 class="ui header" id="vertical-segment">
  69. <!-- <a href="javascript:window.history.back();"><i class="arrow left icon"></i>返回</a> -->
  70. <div class="ui breadcrumb">
  71. <a class="section" href="{{$.RepoLink}}/modelmanage/show_model">
  72. {{$.i18n.Tr "repo.model.manage.model_manage"}}
  73. </a>
  74. <div class="divider"> / </div>
  75. <div class="active section">{{.name}}</div>
  76. </div>
  77. <select class="ui dropdown tiny change-version" id="dropdown" onchange="changeInfo(this.value)">
  78. </select>
  79. </h4>
  80. <div id="showInfo" style="border:1px solid #e2e2e2;padding: 20px 60px;margin-top:24px">
  81. <div class="ui pointing secondary menu" style="border-bottom: 1px solid rgba(34,36,38,.15);">
  82. <a class="active item" data-tab="first">{{$.i18n.Tr "repo.modelarts.train_job.config"}}</a>
  83. <a class="item" data-tab="second">{{$.i18n.Tr "repo.model_download"}}</a>
  84. </div>
  85. <div class="ui tab active" data-tab="first">
  86. <div class="half-table">
  87. <span class="model_header_text">基本信息</span>
  88. <table class="tableStyle" style="margin-top:20px;">
  89. <tbody>
  90. <tr>
  91. <td class="ti-text-form-label text-width80">{{$.i18n.Tr "repo.model.manage.model_name"}}</td>
  92. <td class="ti-text-form-content word-elipsis"><span id="ModelName" title=""></span></td>
  93. </tr>
  94. <tr>
  95. <td class="ti-text-form-label text-width80">{{$.i18n.Tr "repo.model.manage.version"}}</td>
  96. <td class="ti-text-form-content word-elipsis"><span id="Version" title=""></span></td>
  97. </tr>
  98. <tr>
  99. <td class="ti-text-form-label text-width80">{{$.i18n.Tr "repo.migrate_items_labels"}}</td>
  100. <td class="ti-text-form-content">
  101. <div id="Label" style="overflow: hidden;width: 95%;">
  102. </div>
  103. </td>
  104. </tr>
  105. <tr>
  106. <td class="ti-text-form-label text-width80">{{$.i18n.Tr "repo.modelarts.model_size"}}</td>
  107. <td class="ti-text-form-content word-elipsis"><span id="Size" title=""></span></td>
  108. </tr>
  109. <tr>
  110. <td class="ti-text-form-label text-width80">{{$.i18n.Tr "repo.modelarts.createtime"}}</td>
  111. <td class="ti-text-form-content word-elipsis"><span id="CreateTime" title=""></span></td>
  112. </tr>
  113. <tr>
  114. <td class="ti-text-form-label text-width80">{{$.i18n.Tr "repo.model.manage.description"}}</td>
  115. <td class="ti-text-form-content" >
  116. <div id="edit-td" style="display:flex">
  117. <span id="Description" title="" class="iword-elipsis"></span>
  118. <i id="edit-pencil" data-id="" data-desc="" class="pencil alternate icon" style="cursor:pointer;vertical-align: top;" id="editor" onclick="editorFn(this)"></i>
  119. </div>
  120. </td>
  121. </tr>
  122. <tr>
  123. <td class="ti-text-form-label text-width80">{{$.i18n.Tr "repo.modelarts.code_version"}}</td>
  124. <td class="ti-text-form-content word-elipsis"><span id="CodeBranch" title=""></span></td>
  125. </tr>
  126. <tr>
  127. <td class="ti-text-form-label text-width80">{{$.i18n.Tr "repo.modelarts.train_job.start_file"}}</td>
  128. <td class="ti-text-form-content word-elipsis"><span id="BootFile" title=""></span></td>
  129. </tr>
  130. <tr>
  131. <td class="ti-text-form-label text-width80">{{$.i18n.Tr "repo.modelarts.train_job.train_dataset"}}</td>
  132. <td class="ti-text-form-content word-elipsis"><span id="DatasetName" title=""></span></td>
  133. </tr>
  134. <tr>
  135. <td class="ti-text-form-label text-width80">{{$.i18n.Tr "repo.modelarts.train_job.run_parameter"}}</td>
  136. <td class="ti-text-form-content word-elipsis"><span id="Parameters" title=""></span></td>
  137. </tr>
  138. <tr>
  139. <td class="ti-text-form-label text-width80">{{$.i18n.Tr "repo.modelarts.train_job.AI_Engine"}}</td>
  140. <td class="ti-text-form-content word-elipsis"><span id="EngineName" title=""></span></td>
  141. </tr>
  142. <tr>
  143. <td class="ti-text-form-label text-width80">{{$.i18n.Tr "repo.modelarts.train_job.standard"}}</td>
  144. <td class="ti-text-form-content word-elipsis"><span id="FlavorName" title=""></span></td>
  145. </tr>
  146. <tr>
  147. <td class="ti-text-form-label text-width80">{{$.i18n.Tr "repo.modelarts.train_job.compute_node"}}</td>
  148. <td class="ti-text-form-content word-elipsis"><span id="WorkServerNumber" title=""></span></td>
  149. </tr>
  150. </tbody>
  151. </table>
  152. </div>
  153. <div class="half-table">
  154. <span class="model_header_text">{{$.i18n.Tr "repo.model.manage.model_accuracy"}}</span>
  155. <table class="tableStyle" style="margin-top:20px;">
  156. <tbody>
  157. <tr>
  158. <td class="ti-text-form-label text-width80">{{$.i18n.Tr "repo.model.manage.Accuracy"}}</td>
  159. <td class="ti-text-form-content word-elipsis"><span id="Accuracy" title=""></span></td>
  160. </tr>
  161. <tr>
  162. <td class="ti-text-form-label text-width80">F1</td>
  163. <td class="ti-text-form-content word-elipsis"><span id="F1" title=""></span></td>
  164. </tr>
  165. <tr>
  166. <td class="ti-text-form-label text-width80">{{$.i18n.Tr "repo.model.manage.Precision"}}</td>
  167. <td class="ti-text-form-content word-elipsis"><span id="Precision" title=""></span></td>
  168. </tr>
  169. <tr>
  170. <td class="ti-text-form-label text-width80">{{$.i18n.Tr "repo.model.manage.Recall"}}</td>
  171. <td class="ti-text-form-content word-elipsis"><span id="Recall" title=""></span></td>
  172. </tr>
  173. </tbody>
  174. </table>
  175. </div>
  176. <div style="clear: both;"></div>
  177. </div>
  178. <div class="ui tab" data-tab="second">
  179. <input type="hidden" name="model" value="-1">
  180. <input type="hidden" name="modelback" value="-1">
  181. <div class='ui breadcrumb model_file_bread' id='file_breadcrumb'>
  182. <div class="active section"></div>
  183. <div class="divider"> / </div>
  184. </div>
  185. <div id="dir_list">
  186. </div>
  187. </div>
  188. </div>
  189. </div>
  190. </div>
  191. {{template "base/footer" .}}
  192. <script>
  193. let url = location.href.split('show_model')[0]
  194. let ID = location.search.split('?name=').pop()
  195. $(document).ready(function(){
  196. $('.secondary.menu .item').tab();
  197. });
  198. $(document).ready(loadInfo);
  199. function changeInfo(version){
  200. $.get(`${url}show_model_info_api?name=${ID}`,(data)=>{
  201. let versionData = data.filter((item)=>{
  202. return item.Version === version
  203. })
  204. let returnArray = []
  205. returnArray = transObj(versionData)
  206. let [initObj,initModelAcc,id] = returnArray
  207. editorCancel('','')
  208. renderInfo(initObj,initModelAcc,id)
  209. loadModelFile(versionData[0].ID,versionData[0].Version,'','','init')
  210. })
  211. }
  212. function loadInfo(){
  213. $.get(`${url}show_model_info_api?name=${ID}`,(data)=>{
  214. let html = ''
  215. for (let i=0;i<data.length;i++){
  216. if(!data[i].IsCanOper){
  217. $("#edit-pencil").css("display","none")
  218. }
  219. html += `<option value="${data[i].Version}">${data[i].Version}</option>`
  220. }
  221. $('#dropdown').append(html)
  222. let returnArray = []
  223. returnArray = transObj(data)
  224. let [initObj,initModelAcc,id] = returnArray
  225. renderInfo(initObj,initModelAcc,id)
  226. loadModelFile(data[0].ID,data[0].Version,'','','init')
  227. })
  228. }
  229. function getEngineName(model){
  230. if(model.Engine == 0){
  231. return "Pytorch";
  232. }else if(model.Engine == 1 || model.Engine == 121){
  233. return "TensorFlow";
  234. }else if(model.Engine == 2 || model.Engine == 122){
  235. return "MindSpore";
  236. }else{
  237. return "Other"
  238. }
  239. }
  240. function transObj(data){
  241. let {ID,Name,Version,Label,Size,Description,CreatedUnix,Accuracy,CodeBranch,CodeCommitID,TrainTaskInfo} = data[0]
  242. let modelAcc = JSON.parse(Accuracy)
  243. TrainTaskInfo = JSON.parse(TrainTaskInfo)
  244. // Parameters = JSON.parse(Parameters)
  245. let {Parameters} = TrainTaskInfo
  246. let EngineName = getEngineName(data[0])
  247. Parameters = JSON.parse(Parameters)
  248. Parameters = Parameters.parameter.length === 0 ? '--':Parameters.parameter
  249. let size = tranSize(Size)
  250. let time = transTime(CreatedUnix)
  251. let initObj = {
  252. ModelName:Name || '--',
  253. Version:Version,
  254. Label:Label || '--',
  255. Size:size,
  256. CreateTime:time,
  257. Description:Description || '--',
  258. CodeBranch:CodeBranch || '--',
  259. CodeCommitID:CodeCommitID || '--',
  260. BootFile:TrainTaskInfo.BootFile || '--',
  261. DatasetName:TrainTaskInfo.DatasetName || '--',
  262. Parameters:TrainTaskInfo.Parameters || '--',
  263. FlavorName:TrainTaskInfo.FlavorName || '--',
  264. WorkServerNumber:TrainTaskInfo.WorkServerNumber || '--',
  265. Parameters:Parameters,
  266. EngineName:EngineName,
  267. }
  268. let initModelAcc = {
  269. Accuracy: modelAcc.Accuracy || '--',
  270. F1: modelAcc.F1 || '--',
  271. Precision:modelAcc.Precision || '--',
  272. Recall: modelAcc.Recall || '--'
  273. }
  274. return [initObj,initModelAcc,ID]
  275. }
  276. function transTime(time){
  277. let date = new Date(time * 1000);//时间戳为10位需*1000,时间戳为13位的话不需乘1000
  278. let Y = date.getFullYear() + '-';
  279. let M = (date.getMonth()+1 < 10 ? '0'+(date.getMonth()+1):date.getMonth()+1) + '-';
  280. let D = (date.getDate()< 10 ? '0'+date.getDate():date.getDate())+ ' ';
  281. let h = (date.getHours() < 10 ? '0'+date.getHours():date.getHours())+ ':';
  282. let m = (date.getMinutes() < 10 ? '0'+date.getMinutes():date.getMinutes()) + ':';
  283. let s = date.getSeconds() < 10 ? '0'+date.getSeconds():date.getSeconds();
  284. return Y+M+D+h+m+s;
  285. }
  286. function tranSize(value){
  287. if(null==value||value==''){
  288. return "0 Bytes";
  289. }
  290. var unitArr = new Array("Bytes","KB","MB","GB","TB","PB","EB","ZB","YB");
  291. var index=0;
  292. var srcsize = parseFloat(value);
  293. index=Math.floor(Math.log(srcsize)/Math.log(1024));
  294. var size =srcsize/Math.pow(1024,index);
  295. size=size.toFixed(2);//保留的小数位数
  296. return size+unitArr[index];
  297. }
  298. function editorFn(context){
  299. let id= context.dataset.id
  300. let text = context.dataset.desc
  301. let textValue = text.replace(/enter;/g,'\r\n')
  302. $('#edit-td').replaceWith(`<div id='edit-div' style='width:80%;display: inline-block;'><textarea id='textarea-value' value='' rows='3' maxlength='255' style='width:80%;white-space: nowrap;' id='edit-text'>${textValue}</textarea><i class='check icon' style='color: #50d4ab;' onclick='editorSure("${text}","${id}")'></i><i class='times icon' style='color: #f66f6a;' onclick='editorCancel("${text}","${id}")'></i></div>`);
  303. }
  304. function editorCancel(text,id){
  305. let objkey = text.replace(/enter;/g,'\r\n')
  306. $('#edit-div').replaceWith(`<div id="edit-td" style="display:flex;"><span id="Description" title="${objkey}" class="iword-elipsis">${objkey}</span><i id="edit-pencil" data-id="${id}" data-desc="${text}" class="pencil alternate icon" style="cursor:pointer;vertical-align: top;" id="editor" onclick="editorFn(this)"></div>`)
  307. }
  308. function editorSure(text,id){
  309. let description=$('#textarea-value').val()
  310. let sourcetext = $('#textarea-value').val().replace(/\n/g,'enter;')
  311. let data = {
  312. ID:id,
  313. Description:description
  314. }
  315. $.ajax({
  316. url:`${url}modify_model`,
  317. type:'PUT',
  318. data:data
  319. }).done((res)=>{
  320. $('#edit-div').replaceWith(`<div id="edit-td" style="display:flex;"><span id="Description" title="${description}" class="iword-elipsis">${description}</span><i id="edit-pencil" data-id="${id}" data-desc="${sourcetext}" class="pencil alternate icon" style="cursor:pointer;vertical-align: top;" id="editor" onclick="editorFn(this)"></div>`)
  321. })
  322. }
  323. function renderInfo(obj,accObj,id){
  324. for(let key in obj){
  325. if(key==="Description"){
  326. let descriptionText=obj[key].replace(/\r\n|\n/g,'enter;')
  327. $(`#${key}`).text(obj[key])
  328. $(`#${key}`).attr("title",obj[key])
  329. $('#edit-pencil').attr("data-id",id)
  330. $('#edit-pencil').attr("data-desc",descriptionText)
  331. }
  332. else if(key==="Label"){
  333. $('#Label').empty()
  334. if(obj[key]==='--'){
  335. $('#Label').text(obj[key])
  336. }else{
  337. let labelArray = obj[key].trim().replace(/ +/g,' ').split(' ')
  338. let html=''
  339. for(let i=0;i<labelArray.length;i++){
  340. html += `<a class="ui label" title="${labelArray[i]}">${labelArray[i]}</a>`
  341. }
  342. $('#Label').append(html)
  343. }
  344. }
  345. else if(key==="CodeCommitID"){
  346. let codeCommit = obj[key].slice(0,10)
  347. let html = `<a style="margin-left:1rem" class="ui label" title="${codeCommit}">${codeCommit}</a>`
  348. $('#CodeBranch').append(html)
  349. }
  350. else if(key==="Parameters"){
  351. if(obj[key]==='--'){
  352. $(`#${key}`).text(obj[key])
  353. }else{
  354. const parameterArray = obj[key].map(element => {
  355. let labelValue = `${element.label}=${element.value}`
  356. return labelValue
  357. });
  358. const parameter = parameterArray.join('; ')
  359. $(`#${key}`).text(parameter)
  360. $(`#${key}`).attr("title",parameter)
  361. }
  362. }
  363. else{
  364. $(`#${key}`).text(obj[key])
  365. $(`#${key}`).attr("title",obj[key])
  366. }
  367. }
  368. for(let key in accObj){
  369. $(`#${key}`).text(accObj[key])
  370. $(`#${key}`).attr("title",accObj[key])
  371. }
  372. }
  373. function loadModelFile(ID,version_name,parents,filename,init){
  374. $.get(`${url}query_onelevel_modelfile?ID=${ID}&parentDir=${parents}`, (data) => {
  375. $('#dir_list').empty()
  376. renderDir(data,ID,version_name)
  377. if(init==="init"){
  378. $('input[name=model]').val("")
  379. $('input[name=modelback]').val(version_name)
  380. $('#file_breadcrumb').empty()
  381. let htmlBread = ""
  382. htmlBread += `<div class='active section'>${version_name}</div>`
  383. htmlBread += "<div class='divider'> / </div>"
  384. $('#file_breadcrumb').append(htmlBread)
  385. }else{
  386. renderBrend(ID,version_name,parents,filename,init)
  387. }
  388. })
  389. }
  390. function renderSize(value){
  391. if(null==value||value==''){
  392. return "0 Bytes";
  393. }
  394. var unitArr = new Array("Bytes","KB","MB","GB","TB","PB","EB","ZB","YB");
  395. var index=0;
  396. var srcsize = parseFloat(value);
  397. index=Math.floor(Math.log(srcsize)/Math.log(1024));
  398. var size =srcsize/Math.pow(1024,index);
  399. size=size.toFixed(2);//保留的小数位数
  400. return size+unitArr[index];
  401. }
  402. function renderBrend(ID,version_name,parents,filename,init){
  403. if(init=="folder"){
  404. let htmlBrend = ""
  405. let sectionName=$('#file_breadcrumb .active.section').text()
  406. let parents1 = $('input[name=model]').val()
  407. let filename1 = $('input[name=modelback]').val()
  408. if(parents1===""){
  409. $('#file_breadcrumb .active.section').replaceWith(`<a class='section' onclick="loadModelFile('${ID}','${version_name}','${parents1}','','init')">${sectionName}</a>`)
  410. }else{
  411. $('#file_breadcrumb .active.section').replaceWith(`<a class='section' onclick="loadModelFile('${ID}','${version_name}','${parents1}','${filename1}')">${sectionName}</a>`)
  412. }
  413. htmlBrend += `<div class='active section'>${filename}</div>`
  414. htmlBrend += "<div class='divider'> / </div>"
  415. $('#file_breadcrumb').append(htmlBrend)
  416. $('input[name=model]').val(parents)
  417. $('input[name=modelback]').val(filename)
  418. }else{
  419. $('input[name=model]').val(parents)
  420. $('input[name=modelbac]').val(filename)
  421. $('#file_breadcrumb a.section:contains(${filename})').nextAll().remove()
  422. $('#file_breadcrumb a.section:contains(${filename})').replaceWith(`<div class='active section'>${filename}</div>`)
  423. $('#file_breadcrumb div.section:contains(${filename})').append("<div class='divider'> / </div>")
  424. }
  425. }
  426. function renderDir(data,ID,version_name){
  427. let html=""
  428. html += "<div class='ui grid' style='margin:0;'>"
  429. html += "<div class='row' style='padding: 0;'>"
  430. html += "<div class='ui sixteen wide column' style='padding:1rem;'>"
  431. html += "<div class='dir list'>"
  432. html += "<table id='repo-files-table' class='ui single line table pad20'>"
  433. html += '<tbody>'
  434. for(let i=0;i<data.length;i++){
  435. let dirs_size = renderSize(data[i].Size)
  436. html += "<tr>"
  437. html += "<td class='name six wid'>"
  438. html += "<span class='truncate'>"
  439. html += "<span class='octicon octicon-file-directory'>"
  440. html += "</span>"
  441. if(data[i].IsDir){
  442. html += `<a onclick="loadModelFile('${ID}','${version_name}','${data[i].ParenDir}','${data[i].FileName}','folder')">`
  443. html += "<span class='fitted'><i class='folder icon' width='16' height='16' aria-hidden='true'></i>" + data[i].FileName + "</span>"
  444. }else{
  445. html += `<a href="${url}${ID}/downloadsingle?parentDir=${data[i].ParenDir}&fileName=${data[i].FileName}">`
  446. html += "<span class='fitted'><i class='file icon' width='16' height='16' aria-hidden='true'></i>" + data[i].FileName + "</span>"
  447. }
  448. html += '</a>'
  449. html += "</span>"
  450. html += "</td>"
  451. html += "<td class='message seven wide'>"
  452. if(data[i].IsDir){
  453. html += "<span class='truncate has-emoji'></span>"
  454. }else{
  455. html += "<span class='truncate has-emoji'>"+ `${dirs_size}` + "</span>"
  456. }
  457. html += "</td>"
  458. html += "<td class='text right age three wide'>"
  459. html += "<span class='truncate has-emoji'>" + data[i].ModTime + "</span>"
  460. html += "</td>"
  461. html += "</tr>"
  462. }
  463. html += "</tbody>"
  464. html += "</table>"
  465. html += "</div>"
  466. html += "</div>"
  467. html += "</div>"
  468. html += "</div>"
  469. $('#dir_list').append(html)
  470. }
  471. </script>