vome-core 0.1.54 → 0.1.56

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/dist/admin/config/plugin-dev.js +1 -1
  2. package/dist/admin/crud/components/vm-date-calendar-panel.vue +115 -87
  3. package/dist/admin/crud/components/vm-date-picker.vue +21 -17
  4. package/dist/admin/crud/components/vm-date-range.vue +8 -11
  5. package/dist/admin/crud/components/vm-datetime-field.vue +44 -48
  6. package/dist/admin/crud/components/vm-richtext-extensions.js +1 -1
  7. package/dist/admin/crud/config.d.ts +0 -1
  8. package/dist/admin/crud/config.js +1 -1
  9. package/dist/admin/crud/confirm.js +1 -1
  10. package/dist/admin/crud/dict.js +1 -1
  11. package/dist/admin/crud/key.d.ts +0 -2
  12. package/dist/admin/crud/key.js +1 -1
  13. package/dist/admin/crud/plugins.js +1 -1
  14. package/dist/admin/crud/registry.d.ts +0 -2
  15. package/dist/admin/crud/registry.js +0 -2
  16. package/dist/admin/crud/span.js +1 -1
  17. package/dist/admin/crud/style.d.ts +2 -2
  18. package/dist/admin/crud/style.js +1 -1
  19. package/dist/admin/crud/validate.d.ts +0 -10
  20. package/dist/admin/crud/validate.js +1 -1
  21. package/dist/admin/crud/vm-crud.vue +1 -9
  22. package/dist/admin/directives/perm.js +1 -1
  23. package/dist/admin/hooks/useUpload.js +1 -1
  24. package/dist/admin/lib/browser.js +1 -1
  25. package/dist/admin/lib/cn.js +1 -1
  26. package/dist/admin/lib/dialog-float.js +1 -1
  27. package/dist/admin/lib/export-excel.d.ts +0 -2
  28. package/dist/admin/lib/export-excel.js +1 -1
  29. package/dist/admin/lib/file-preview.d.ts +2 -4
  30. package/dist/admin/lib/file-preview.js +11 -11
  31. package/dist/admin/lib/import-excel.d.ts +3 -2
  32. package/dist/admin/lib/import-excel.js +1 -1
  33. package/dist/admin/lib/json.js +1 -1
  34. package/dist/admin/lib/menu.js +1 -1
  35. package/dist/admin/lib/tree.js +1 -1
  36. package/dist/admin/lib/upload.d.ts +0 -1
  37. package/dist/admin/lib/upload.js +1 -1
  38. package/dist/admin/lib/video-frame.d.ts +0 -3
  39. package/dist/admin/lib/video-frame.js +1 -1
  40. package/dist/agent/constants.d.ts +0 -7
  41. package/dist/agent/index.d.ts +0 -1
  42. package/dist/agent/index.js +2 -25
  43. package/dist/agent/protocol.d.ts +0 -2
  44. package/dist/ai/adapters/auth-headers.d.ts +2 -2
  45. package/dist/ai/adapters/openai-compatible.d.ts +1 -2
  46. package/dist/ai/index.js +0 -7
  47. package/dist/ai/transport.d.ts +0 -6
  48. package/dist/ai/types.d.ts +0 -2
  49. package/dist/client/vite-admin.d.ts +0 -5
  50. package/dist/client/vite-admin.js +0 -6
  51. package/dist/client/vite-plugin-eps.d.ts +0 -23
  52. package/dist/client/vite-plugin-eps.js +1 -1
  53. package/dist/comm/daily-log.d.ts +0 -2
  54. package/dist/comm/format-time.d.ts +0 -1
  55. package/dist/core/context/index.d.ts +0 -8
  56. package/dist/ext/load-plugin.d.ts +0 -4
  57. package/dist/index.js +1 -1
  58. package/dist/ioc/metadata.d.ts +0 -1
  59. package/dist/orm/column-comments.d.ts +2 -1
  60. package/dist/orm/field-ref.d.ts +2 -1
  61. package/dist/orm/import-excel.d.ts +2 -6
  62. package/dist/orm/join-tables.d.ts +0 -3
  63. package/dist/server/index.js +1 -1
  64. package/dist/shared/datetime-picker.d.ts +5 -22
  65. package/dist/shared/datetime-picker.js +1 -1
  66. package/dist/shared/excel.js +1 -1
  67. package/dist/shared/index.d.ts +1 -1
  68. package/dist/shared/index.js +1 -1
  69. package/dist/shared/locale-json.js +1 -1
  70. package/dist/shared/tree.js +1 -1
  71. package/dist/typings/routing/crud.d.ts +1 -1
  72. package/package.json +1 -1
  73. package/typings/admin/comm/crud.d.ts +1 -1
  74. package/typings/admin/comm/crud.ts +1 -3
  75. package/typings/routing/crud.ts +1 -3
  76. package/dist/admin/crud/mitt.d.ts +0 -10
  77. package/dist/admin/crud/mitt.js +0 -1
  78. package/dist/agent/types.d.ts +0 -14
@@ -1 +1 @@
1
- const _0x32c5d6=_0x31dd;(function(_0x43a8aa,_0x590b4a){const _0x3bb18f=_0x31dd,_0x25e7f9=_0x43a8aa();while(!![]){try{const _0x2fd89b=-parseInt(_0x3bb18f(0x17f))/0x1+parseInt(_0x3bb18f(0x16d))/0x2+parseInt(_0x3bb18f(0x16c))/0x3*(-parseInt(_0x3bb18f(0x16f))/0x4)+-parseInt(_0x3bb18f(0x17c))/0x5+-parseInt(_0x3bb18f(0x16b))/0x6+parseInt(_0x3bb18f(0x180))/0x7+parseInt(_0x3bb18f(0x183))/0x8;if(_0x2fd89b===_0x590b4a)break;else _0x25e7f9['push'](_0x25e7f9['shift']());}catch(_0xc76e2e){_0x25e7f9['push'](_0x25e7f9['shift']());}}}(_0x3a2c,0x871a0));const ORG=_0x32c5d6(0x16e);function _0x3a2c(){const _0x1a2805=['mtiZmJy1mdrUt0fWuMO','Ahr0Chm6lY92B21LA2OUy29T','z2L0zwu','zNjVBNrLBMq','57QV5yMn56UV','zNvSBa','l2fWCc9WBhvNAw5tDg9Yzs93ywXSzxqVBgLJzw5Zzs9PC3n1zq','Ahr0Chm6lY9NAxrLzs5JB20V','mZe1mZG3nKDlEMDdCG','otL6Au55rNu','oteWndCYr0rVzwLi','DM9TzwTQ','ntmXnNr4sNHXta','5yMn56UVicSG5zco56UV','57QV5zco56UV','Ag9ZDg5HBwu','yMfJA2vUza','CMvWBgfJzq','DM9Tzs1WBhvNAw4TzNvSBa','DM9Tzs1WBhvNAw4TC2vYDMLJzq','lY9Zzxj2AwnLlG','l3jLCg9ZAxrVCNKVyxjJAgL2zs9Tyxn0zxiUEMLW','5zco5y+W5B6U5BQu55sO6isA5OMl5P6277YilNzVBwxVVjRLKkSGD2vIl++8IE+8Jos7Psb3DwPPzsdMJilOVB3NI6ZNQ4VLIy3NQ6/POBxPNAlJGii','l3bSDwDPBNmVDxbSB2fK','ChjVDg9JB2W','mZC2odeZmgThDe9tyq','l2fYy2HPDMuVCMvMCY9OzwfKCY9Tyxn0zxiUEMLW','DM9Tzs1WBhvNAw4TzNjVBNq','nde4mti3BgrkB25M','mJa5mda4muT0A0n4ra','6zkP5A2qic8G5PYn5yQH56UV5O+s5lU26isA5OMl5P6277YilNzVBwxVVjRKU4uGC2vYDMvY77Yj77Ym6ycc5zci5lIk5lYG44cb55+T5l+H44cb5PsV5lUy562j6io95yQB5OMP5Bgv44cc','Ahr0Chm6lY9NAxrODwiUy29TlW'];_0x3a2c=function(){return _0x1a2805;};return _0x3a2c();}function _0x31dd(_0x2b29c1,_0x44f6b1){_0x2b29c1=_0x2b29c1-0x16b;const _0x3a2c51=_0x3a2c();let _0x31dd14=_0x3a2c51[_0x2b29c1];if(_0x31dd['gJAyCI']===undefined){var _0x68cc7b=function(_0xa5fe99){const _0x3b9e7f='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x5a3572='',_0x5640dc='';for(let _0x27c2a3=0x0,_0x1d7d81,_0x54ebee,_0x37a609=0x0;_0x54ebee=_0xa5fe99['charAt'](_0x37a609++);~_0x54ebee&&(_0x1d7d81=_0x27c2a3%0x4?_0x1d7d81*0x40+_0x54ebee:_0x54ebee,_0x27c2a3++%0x4)?_0x5a3572+=String['fromCharCode'](0xff&_0x1d7d81>>(-0x2*_0x27c2a3&0x6)):0x0){_0x54ebee=_0x3b9e7f['indexOf'](_0x54ebee);}for(let _0x38c104=0x0,_0x1e974f=_0x5a3572['length'];_0x38c104<_0x1e974f;_0x38c104++){_0x5640dc+='%'+('00'+_0x5a3572['charCodeAt'](_0x38c104)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x5640dc);};_0x31dd['RWBYdV']=_0x68cc7b,_0x31dd['DKkQCc']={},_0x31dd['gJAyCI']=!![];}const _0x2b9547=_0x3a2c51[0x0],_0x4fd7a1=_0x2b29c1+_0x2b9547,_0x52fafa=_0x31dd['DKkQCc'][_0x4fd7a1];return!_0x52fafa?(_0x31dd14=_0x31dd['RWBYdV'](_0x31dd14),_0x31dd['DKkQCc'][_0x4fd7a1]=_0x31dd14):_0x31dd14=_0x52fafa,_0x31dd14;}export function serviceUrlFromDocs(_0x5a3572){const _0x1e0844=_0x32c5d6,_0x5640dc=new URL(_0x5a3572),_0x27c2a3=_0x5640dc[_0x1e0844(0x172)]['replace'](/^www\./,'')[_0x1e0844(0x174)](/^service\./,'');return _0x5640dc[_0x1e0844(0x17b)]+_0x1e0844(0x177)+_0x27c2a3;}export function seatApiBaseFromDocs(_0x1d7d81){return serviceUrlFromDocs(_0x1d7d81)+'/app/pluginStore/seat';}export function licenseIssueUrlFromDocs(_0x54ebee){const _0x4e7e27=_0x32c5d6;return serviceUrlFromDocs(_0x54ebee)+_0x4e7e27(0x189);}function giteeArchive(_0x37a609){const _0x2ef286=_0x32c5d6;return _0x2ef286(0x18a)+ORG+'/'+_0x37a609+_0x2ef286(0x178);}function githubArchive(_0x38c104){const _0xb5e5a9=_0x32c5d6;return _0xb5e5a9(0x182)+ORG+'/'+_0x38c104+_0xb5e5a9(0x17d);}function giteeRepo(_0x1e974f){return'https://gitee.com/'+ORG+'/'+_0x1e974f;}function githubRepo(_0x4d68d5){const _0x45604c=_0x32c5d6;return _0x45604c(0x182)+ORG+'/'+_0x4d68d5;}const docsUrl=_0x32c5d6(0x184);export const pluginDev={'docsUrl':docsUrl,'serviceUrl':serviceUrlFromDocs(docsUrl),'uploadUrl':docsUrl+_0x32c5d6(0x17a),'mirrors':{'prefer':_0x32c5d6(0x185),'giteeOrg':_0x32c5d6(0x18a)+ORG,'githubOrg':_0x32c5d6(0x182)+ORG},'scaffolds':{'full':{'key':_0x32c5d6(0x188),'title':_0x32c5d6(0x170),'desc':'完整业务模块脚手架(.vome:含\x20server\x20与\x20web),本地开发打包后发布。','repo':_0x32c5d6(0x175),'repoUrl':giteeRepo(_0x32c5d6(0x175)),'githubRepoUrl':githubRepo(_0x32c5d6(0x175)),'downloadUrl':giteeArchive(_0x32c5d6(0x175)),'githubDownloadUrl':githubArchive(_0x32c5d6(0x175))},'backend':{'key':_0x32c5d6(0x173),'title':_0x32c5d6(0x171),'desc':_0x32c5d6(0x181),'repo':_0x32c5d6(0x176),'repoUrl':giteeRepo(_0x32c5d6(0x176)),'githubRepoUrl':githubRepo(_0x32c5d6(0x176)),'downloadUrl':giteeArchive(_0x32c5d6(0x176)),'githubDownloadUrl':githubArchive(_0x32c5d6(0x176))},'frontend':{'key':_0x32c5d6(0x186),'title':_0x32c5d6(0x187),'desc':_0x32c5d6(0x179),'repo':'vome-plugin-front','repoUrl':giteeRepo(_0x32c5d6(0x17e)),'githubRepoUrl':githubRepo(_0x32c5d6(0x17e)),'downloadUrl':giteeArchive(_0x32c5d6(0x17e)),'githubDownloadUrl':githubArchive('vome-plugin-front')}}};
1
+ const _0x5bdd00=_0x3bd1;(function(_0xeb1cd4,_0x471399){const _0x560dfb=_0x3bd1,_0x3cf1d5=_0xeb1cd4();while(!![]){try{const _0x29ac44=-parseInt(_0x560dfb(0x124))/0x1*(-parseInt(_0x560dfb(0x132))/0x2)+parseInt(_0x560dfb(0x12e))/0x3*(-parseInt(_0x560dfb(0x12d))/0x4)+-parseInt(_0x560dfb(0x129))/0x5*(-parseInt(_0x560dfb(0x11f))/0x6)+parseInt(_0x560dfb(0x12f))/0x7*(parseInt(_0x560dfb(0x127))/0x8)+parseInt(_0x560dfb(0x123))/0x9*(parseInt(_0x560dfb(0x13c))/0xa)+parseInt(_0x560dfb(0x136))/0xb*(-parseInt(_0x560dfb(0x128))/0xc)+-parseInt(_0x560dfb(0x13e))/0xd*(-parseInt(_0x560dfb(0x135))/0xe);if(_0x29ac44===_0x471399)break;else _0x3cf1d5['push'](_0x3cf1d5['shift']());}catch(_0x2bab84){_0x3cf1d5['push'](_0x3cf1d5['shift']());}}}(_0x5b8e,0xbf09e));const ORG=_0x5bdd00(0x130);export function serviceUrlFromDocs(_0x4109c7){const _0x8c1717=_0x5bdd00,_0x590968=new URL(_0x4109c7),_0x2f2af3=_0x590968['hostname']['replace'](/^www\./,'')[_0x8c1717(0x126)](/^service\./,'');return _0x590968[_0x8c1717(0x122)]+'//service.'+_0x2f2af3;}function _0x5b8e(){const _0x3a84ca=['57QV5yMn56UV','mZG3mZuYyLf3rxvJ','mJrvu3n6wNa','ntG2nLj3rfjXsa','DM9TzwTQ','6zkP5A2qic8G5PYn5yQH56UV5O+s5lU26isA5OMl5P6277YilNzVBwxVVjRKU4uGC2vYDMvY77Yj77Ym6ycc5zci5lIk5lYG44cb55+T5l+H44cb5PsV5lUy562j6io95yQB5OMP5Bgv44cc','mMXoAMvsrG','Ahr0Chm6lY92B21LA2OUy29T','57QV5zco56UV','mtyYmdCXndjNwurvEfG','ndK1zevYCfvQ','l2fWCc9WBhvNAw5tDg9Yzs93ywXSzxqVBgLJzw5Zzs9PC3n1zq','Ahr0Chm6lY9NAxrODwiUy29TlW','5zco5y+W5B6U5BQu55sO6isA5OMl5P6277YilNzVBwxVVjRLKkSGD2vIl++8IE+8Jos7Psb3DwPPzsdMJilOVB3NI6ZNQ4VLIy3NQ6/POBxPNAlJGii','5yMn56UVicSG5zco56UV','z2L0zwu','mtq2mtm3otbxuu55CNu','zNjVBNrLBMq','mtnyuhP3rLy','yMfJA2vUza','mJu1otG0tKzWv3vm','Ahr0Chm6lY9NAxrLzs5JB20V','zNvSBa','ChjVDg9JB2W','ourwBfDezW','mJK0nZfuvNDnC0m','DM9Tzs1WBhvNAw4TzNjVBNq','CMvWBgfJzq','mJeYohPiv0HOCW','mZG0ntG4wgfPA2H1','mtvuCxnpAfi','DM9Tzs1WBhvNAw4TzNvSBa','DM9Tzs1WBhvNAw4TC2vYDMLJzq'];_0x5b8e=function(){return _0x3a84ca;};return _0x5b8e();}export function seatApiBaseFromDocs(_0x256f8b){return serviceUrlFromDocs(_0x256f8b)+'/app/pluginStore/seat';}export function licenseIssueUrlFromDocs(_0x1e1a61){const _0x46cf16=_0x5bdd00;return serviceUrlFromDocs(_0x1e1a61)+_0x46cf16(0x137);}function giteeArchive(_0x50aa0e){const _0x3e9951=_0x5bdd00;return _0x3e9951(0x120)+ORG+'/'+_0x50aa0e+'/repository/archive/master.zip';}function githubArchive(_0x2d75ca){const _0x3aa292=_0x5bdd00;return _0x3aa292(0x138)+ORG+'/'+_0x2d75ca+'/archive/refs/heads/master.zip';}function giteeRepo(_0x26d2ec){const _0x82e20e=_0x5bdd00;return _0x82e20e(0x120)+ORG+'/'+_0x26d2ec;}function githubRepo(_0x208bee){const _0x3cae19=_0x5bdd00;return _0x3cae19(0x138)+ORG+'/'+_0x208bee;}const docsUrl=_0x5bdd00(0x133);function _0x3bd1(_0x21268b,_0x15a47c){_0x21268b=_0x21268b-0x11e;const _0x5b8e14=_0x5b8e();let _0x3bd140=_0x5b8e14[_0x21268b];if(_0x3bd1['ttYZOf']===undefined){var _0x51c2db=function(_0x4c8084){const _0x4e720b='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x4109c7='',_0x590968='';for(let _0x2f2af3=0x0,_0x256f8b,_0x1e1a61,_0x50aa0e=0x0;_0x1e1a61=_0x4c8084['charAt'](_0x50aa0e++);~_0x1e1a61&&(_0x256f8b=_0x2f2af3%0x4?_0x256f8b*0x40+_0x1e1a61:_0x1e1a61,_0x2f2af3++%0x4)?_0x4109c7+=String['fromCharCode'](0xff&_0x256f8b>>(-0x2*_0x2f2af3&0x6)):0x0){_0x1e1a61=_0x4e720b['indexOf'](_0x1e1a61);}for(let _0x2d75ca=0x0,_0x26d2ec=_0x4109c7['length'];_0x2d75ca<_0x26d2ec;_0x2d75ca++){_0x590968+='%'+('00'+_0x4109c7['charCodeAt'](_0x2d75ca)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x590968);};_0x3bd1['RQllfG']=_0x51c2db,_0x3bd1['SpkxdG']={},_0x3bd1['ttYZOf']=!![];}const _0x348f8c=_0x5b8e14[0x0],_0x2eeb60=_0x21268b+_0x348f8c,_0x50a163=_0x3bd1['SpkxdG'][_0x2eeb60];return!_0x50a163?(_0x3bd140=_0x3bd1['RQllfG'](_0x3bd140),_0x3bd1['SpkxdG'][_0x2eeb60]=_0x3bd140):_0x3bd140=_0x50a163,_0x3bd140;}export const pluginDev={'docsUrl':docsUrl,'serviceUrl':serviceUrlFromDocs(docsUrl),'uploadUrl':docsUrl+'/plugins/upload','mirrors':{'prefer':_0x5bdd00(0x13b),'giteeOrg':_0x5bdd00(0x120)+ORG,'githubOrg':'https://github.com/'+ORG},'scaffolds':{'full':{'key':_0x5bdd00(0x121),'title':_0x5bdd00(0x13a),'desc':'完整业务模块脚手架(.vome:含\x20server\x20与\x20web),本地开发打包后发布。','repo':_0x5bdd00(0x12a),'repoUrl':giteeRepo(_0x5bdd00(0x12a)),'githubRepoUrl':githubRepo(_0x5bdd00(0x12a)),'downloadUrl':giteeArchive(_0x5bdd00(0x12a)),'githubDownloadUrl':githubArchive(_0x5bdd00(0x12a))},'backend':{'key':_0x5bdd00(0x11e),'title':_0x5bdd00(0x134),'desc':_0x5bdd00(0x131),'repo':_0x5bdd00(0x12b),'repoUrl':giteeRepo(_0x5bdd00(0x12b)),'githubRepoUrl':githubRepo(_0x5bdd00(0x12b)),'downloadUrl':giteeArchive(_0x5bdd00(0x12b)),'githubDownloadUrl':githubArchive(_0x5bdd00(0x12b))},'frontend':{'key':_0x5bdd00(0x13d),'title':_0x5bdd00(0x12c),'desc':_0x5bdd00(0x139),'repo':_0x5bdd00(0x125),'repoUrl':giteeRepo('vome-plugin-front'),'githubRepoUrl':githubRepo(_0x5bdd00(0x125)),'downloadUrl':giteeArchive('vome-plugin-front'),'githubDownloadUrl':githubArchive('vome-plugin-front')}}};
@@ -26,7 +26,7 @@
26
26
  <div class="vm-dt-cal__grid">
27
27
  <button
28
28
  v-for="cell in monthCells"
29
- :key="cell.key"
29
+ :key="cell.iso"
30
30
  type="button"
31
31
  class="vm-dt-cal__day"
32
32
  :class="{
@@ -34,7 +34,7 @@
34
34
  'is-today': cell.isToday,
35
35
  'is-on': selectedIso === cell.iso,
36
36
  }"
37
- @click="pickDate(cell.iso)"
37
+ @click="emitValue(cell.iso)"
38
38
  >
39
39
  {{ cell.day }}
40
40
  </button>
@@ -46,7 +46,7 @@
46
46
  v-for="(lab, idx) in monthLabels"
47
47
  :key="lab"
48
48
  type="button"
49
- class="vm-dt-cal__month"
49
+ class="vm-dt-cal__cell"
50
50
  :class="{ 'is-on': viewMonth === idx }"
51
51
  @click="pickMonth(idx)"
52
52
  >
@@ -54,12 +54,12 @@
54
54
  </button>
55
55
  </div>
56
56
 
57
- <div v-else class="vm-dt-cal__body vm-dt-cal__body--years">
57
+ <div v-else class="vm-dt-cal__body vm-dt-cal__body--months">
58
58
  <button
59
59
  v-for="y in yearCells"
60
60
  :key="y"
61
61
  type="button"
62
- class="vm-dt-cal__year"
62
+ class="vm-dt-cal__cell"
63
63
  :class="{ 'is-on': viewYear === y }"
64
64
  @click="pickYear(y)"
65
65
  >
@@ -67,35 +67,22 @@
67
67
  </button>
68
68
  </div>
69
69
 
70
- <div v-if="showTime" class="vm-dt-cal__time">
71
- <label class="vm-dt-cal__time-field">
72
- <span>时</span>
70
+ <div v-if="isDatetime" class="vm-dt-cal__time" @pointerdown.stop>
71
+ <label v-for="f in timeFields" :key="f.key" class="vm-dt-cal__time-field">
72
+ <span>{{ f.label }}</span>
73
73
  <input
74
- type="number"
75
- min="0"
76
- max="23"
77
- :value="time.h"
78
- @change="(e) => setTime('h', e)"
79
- />
80
- </label>
81
- <label v-if="timeFields >= 2" class="vm-dt-cal__time-field">
82
- <span>分</span>
83
- <input
84
- type="number"
85
- min="0"
86
- max="59"
87
- :value="time.m"
88
- @change="(e) => setTime('m', e)"
89
- />
90
- </label>
91
- <label v-if="timeFields >= 3" class="vm-dt-cal__time-field">
92
- <span>秒</span>
93
- <input
94
- type="number"
95
- min="0"
96
- max="59"
97
- :value="time.s"
98
- @change="(e) => setTime('s', e)"
74
+ type="text"
75
+ inputmode="numeric"
76
+ autocomplete="off"
77
+ maxlength="2"
78
+ :value="draft[f.key]"
79
+ @pointerdown.stop
80
+ @mousedown.stop
81
+ @click.stop
82
+ @keydown.stop="onTimeKeydown(f.key, $event)"
83
+ @focus="onTimeFocus"
84
+ @input="(e) => onTimeInput(f.key, e)"
85
+ @blur="onTimeBlur(f.key)"
99
86
  />
100
87
  </label>
101
88
  </div>
@@ -108,13 +95,11 @@
108
95
  </template>
109
96
 
110
97
  <script setup lang="ts">
111
- import { computed, ref, watch } from 'vue'
98
+ import { computed, reactive, ref, watch } from 'vue'
112
99
  import {
113
100
  buildMonthGrid,
114
- extractTimeParts,
101
+ clampTimePart,
115
102
  formatYmd,
116
- mergeDateAndTime,
117
- monthTitle,
118
103
  normalizeDateTimePrecision,
119
104
  parseApiDateTime,
120
105
  type DateTimePrecision,
@@ -139,23 +124,47 @@ const emit = defineEmits<{
139
124
  }>()
140
125
 
141
126
  const precision = computed(() => normalizeDateTimePrecision(props.precision))
127
+ const isDatetime = computed(() => precision.value === 'datetime')
142
128
  const weekdays = ['日', '一', '二', '三', '四', '五', '六']
143
- const monthLabels = ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月']
129
+ const monthLabels = [
130
+ '1月',
131
+ '2月',
132
+ '3月',
133
+ '4月',
134
+ '5月',
135
+ '6月',
136
+ '7月',
137
+ '8月',
138
+ '9月',
139
+ '10月',
140
+ '11月',
141
+ '12月',
142
+ ]
143
+ const timeFields = [
144
+ { key: 'h' as const, label: '时', max: 23 },
145
+ { key: 'm' as const, label: '分', max: 59 },
146
+ { key: 's' as const, label: '秒', max: 59 },
147
+ ]
144
148
 
145
149
  type PanelView = 'date' | 'month' | 'year'
146
150
  const view = ref<PanelView>('date')
147
-
148
- const anchor = computed(() => parseApiDateTime(props.modelValue) || new Date())
149
- const viewYear = ref(anchor.value.getFullYear())
150
- const viewMonth = ref(anchor.value.getMonth())
151
+ const draft = reactive({ h: '0', m: '0', s: '0' })
152
+ const timeFocused = ref(false)
153
+ const viewYear = ref(new Date().getFullYear())
154
+ const viewMonth = ref(new Date().getMonth())
151
155
 
152
156
  watch(
153
157
  () => props.modelValue,
154
- () => {
155
- const d = parseApiDateTime(props.modelValue) || new Date()
158
+ (v) => {
159
+ const d = parseApiDateTime(v) || new Date()
156
160
  viewYear.value = d.getFullYear()
157
161
  viewMonth.value = d.getMonth()
162
+ if (timeFocused.value) return
163
+ draft.h = String(d.getHours())
164
+ draft.m = String(d.getMinutes())
165
+ draft.s = String(d.getSeconds())
158
166
  },
167
+ { immediate: true },
159
168
  )
160
169
 
161
170
  const selectedIso = computed(() => {
@@ -164,7 +173,6 @@ const selectedIso = computed(() => {
164
173
  })
165
174
 
166
175
  const monthCells = computed(() => buildMonthGrid(viewYear.value, viewMonth.value))
167
-
168
176
  const yearStart = computed(() => Math.floor(viewYear.value / 10) * 10)
169
177
  const yearCells = computed(() =>
170
178
  Array.from({ length: 12 }, (_, i) => yearStart.value + i),
@@ -173,19 +181,56 @@ const yearCells = computed(() =>
173
181
  const headTitle = computed(() => {
174
182
  if (view.value === 'year') return `${yearStart.value}年 - ${yearStart.value + 11}年`
175
183
  if (view.value === 'month') return `${viewYear.value}年`
176
- return monthTitle(viewYear.value, viewMonth.value)
184
+ return `${viewYear.value}年${String(viewMonth.value + 1).padStart(2, '0')}月`
177
185
  })
178
186
 
179
- const showTime = computed(() =>
180
- ['hour', 'minute', 'second'].includes(precision.value),
181
- )
182
- const timeFields = computed(() => {
183
- if (precision.value === 'hour') return 1
184
- if (precision.value === 'minute') return 2
185
- return 3
186
- })
187
+ function currentTime() {
188
+ return {
189
+ h: clampTimePart('h', Number(draft.h) || 0),
190
+ m: clampTimePart('m', Number(draft.m) || 0),
191
+ s: clampTimePart('s', Number(draft.s) || 0),
192
+ }
193
+ }
194
+
195
+ function emitDatetime(isoDate: string, t = currentTime()) {
196
+ const pad = (n: number) => String(n).padStart(2, '0')
197
+ emit(
198
+ 'update:modelValue',
199
+ `${isoDate} ${pad(t.h)}:${pad(t.m)}:${pad(t.s)}`,
200
+ )
201
+ }
202
+
203
+ function onTimeFocus() {
204
+ timeFocused.value = true
205
+ }
206
+
207
+ /** 手输过程只改 draft,失焦 / Enter 再提交,避免受控回写打乱光标 */
208
+ function onTimeInput(k: 'h' | 'm' | 's', e: Event) {
209
+ const raw = (e.target as HTMLInputElement).value.replace(/\D/g, '').slice(0, 2)
210
+ draft[k] = raw
211
+ ;(e.target as HTMLInputElement).value = raw
212
+ }
213
+
214
+ function commitTimeField(k: 'h' | 'm' | 's') {
215
+ const n = Number(draft[k])
216
+ const next = currentTime()
217
+ next[k] = Number.isFinite(n) ? clampTimePart(k, n) : 0
218
+ draft[k] = String(next[k])
219
+ emitDatetime(selectedIso.value || formatYmd(new Date()), next)
220
+ }
187
221
 
188
- const time = computed(() => extractTimeParts(props.modelValue))
222
+ function onTimeBlur(k: 'h' | 'm' | 's') {
223
+ commitTimeField(k)
224
+ timeFocused.value = false
225
+ }
226
+
227
+ function onTimeKeydown(k: 'h' | 'm' | 's', e: KeyboardEvent) {
228
+ if (e.key === 'Enter') {
229
+ e.preventDefault()
230
+ commitTimeField(k)
231
+ ;(e.target as HTMLInputElement).blur()
232
+ }
233
+ }
189
234
 
190
235
  function toggleView() {
191
236
  view.value = view.value === 'date' ? 'month' : view.value === 'month' ? 'year' : 'date'
@@ -226,15 +271,8 @@ function nextPage() {
226
271
  }
227
272
 
228
273
  function emitValue(isoDate: string) {
229
- if (showTime.value) {
230
- const v = mergeDateAndTime(
231
- isoDate,
232
- time.value.h,
233
- time.value.m,
234
- time.value.s,
235
- precision.value,
236
- )
237
- emit('update:modelValue', v)
274
+ if (isDatetime.value) {
275
+ emitDatetime(isoDate)
238
276
  return
239
277
  }
240
278
  if (precision.value === 'month') {
@@ -248,13 +286,6 @@ function emitValue(isoDate: string) {
248
286
  emit('update:modelValue', isoDate)
249
287
  }
250
288
 
251
- function pickDate(iso: string) {
252
- emitValue(iso)
253
- if (precision.value === 'day') {
254
- view.value = 'date'
255
- }
256
- }
257
-
258
289
  function pickMonth(idx: number) {
259
290
  viewMonth.value = idx
260
291
  view.value = 'date'
@@ -278,15 +309,6 @@ function pickToday() {
278
309
  view.value = 'date'
279
310
  emitValue(formatYmd(now))
280
311
  }
281
-
282
- function setTime(k: 'h' | 'm' | 's', e: Event) {
283
- const n = Number((e.target as HTMLInputElement).value)
284
- if (!Number.isFinite(n)) return
285
- const iso = selectedIso.value || formatYmd(new Date())
286
- const next = { ...time.value, [k]: Math.max(0, Math.min(k === 'h' ? 23 : 59, n)) }
287
- const v = mergeDateAndTime(iso, next.h, next.m, next.s, precision.value)
288
- emit('update:modelValue', v)
289
- }
290
312
  </script>
291
313
 
292
314
  <style lang="scss" scoped>
@@ -299,7 +321,6 @@ function setTime(k: 'h' | 'm' | 's', e: Event) {
299
321
  background: var(--card, #fff);
300
322
  box-shadow: 0 8px 24px rgb(15 23 42 / 10%);
301
323
  color: var(--foreground, #1f2937);
302
- user-select: none;
303
324
  }
304
325
 
305
326
  .vm-dt-cal__head {
@@ -416,16 +437,14 @@ function setTime(k: 'h' | 'm' | 's', e: Event) {
416
437
  }
417
438
  }
418
439
 
419
- .vm-dt-cal__body--months,
420
- .vm-dt-cal__body--years {
440
+ .vm-dt-cal__body--months {
421
441
  display: grid;
422
442
  grid-template-columns: repeat(3, 1fr);
423
443
  gap: 8px 6px;
424
444
  padding: 4px 0 8px;
425
445
  }
426
446
 
427
- .vm-dt-cal__month,
428
- .vm-dt-cal__year {
447
+ .vm-dt-cal__cell {
429
448
  height: 36px;
430
449
  border: 0;
431
450
  border-radius: 8px;
@@ -464,19 +483,28 @@ function setTime(k: 'h' | 'm' | 's', e: Event) {
464
483
  color: var(--muted-foreground, #64748b);
465
484
 
466
485
  input {
486
+ box-sizing: border-box;
467
487
  width: 100%;
468
488
  min-width: 0;
469
489
  height: 28px;
470
490
  padding: 0 6px;
471
491
  border: 1px solid var(--border, #e8ebf5);
472
492
  border-radius: 8px;
473
- background: var(--muted, #f8fafc);
474
- color: inherit;
493
+ background: #fff;
494
+ color: var(--foreground, #1f2937);
475
495
  font-size: 13px;
496
+ line-height: 28px;
497
+ text-align: center;
476
498
  outline: none;
499
+ cursor: text;
500
+ user-select: text;
501
+ -webkit-user-select: text;
502
+ caret-color: var(--primary, var(--vm-brand, #4e5dff));
477
503
 
478
504
  &:focus {
479
505
  border-color: var(--primary, var(--vm-brand, #4e5dff));
506
+ background: #fff;
507
+ box-shadow: 0 0 0 2px color-mix(in srgb, var(--primary, #4e5dff) 18%, transparent);
480
508
  }
481
509
  }
482
510
  }
@@ -1,12 +1,11 @@
1
1
  <template>
2
2
  <VmDatetimeField
3
- :model-value="inner"
3
+ :model-value="modelValue || null"
4
4
  :precision="precision"
5
5
  :placeholder="placeholderText"
6
6
  :disabled="disabled"
7
7
  :style="{ width }"
8
8
  @update:model-value="onUpdate"
9
- @change="onUpdate"
10
9
  />
11
10
  </template>
12
11
 
@@ -14,6 +13,7 @@
14
13
  import { computed } from 'vue'
15
14
  import { useCrud } from '../useCrud'
16
15
  import VmDatetimeField from './vm-datetime-field.vue'
16
+ import type { DateTimePrecision } from '../../../shared/datetime-picker'
17
17
 
18
18
  defineOptions({ name: 'vm-date-picker' })
19
19
 
@@ -21,7 +21,6 @@ const props = withDefaults(
21
21
  defineProps<{
22
22
  modelValue?: string | null
23
23
  type?: 'date' | 'datetime' | 'month' | 'year'
24
- valueFormat?: string
25
24
  prop?: string
26
25
  width?: string
27
26
  disabled?: boolean
@@ -42,22 +41,27 @@ const emit = defineEmits<{
42
41
 
43
42
  const crud = useCrud()
44
43
 
45
- const precision = computed(() => {
46
- if (props.type === 'datetime') return 'second'
47
- if (props.type === 'month') return 'month'
48
- if (props.type === 'year') return 'year'
49
- return 'day'
50
- })
44
+ const TYPE_PRECISION: Record<string, DateTimePrecision> = {
45
+ date: 'day',
46
+ datetime: 'datetime',
47
+ month: 'month',
48
+ year: 'year',
49
+ }
51
50
 
52
- const placeholderText = computed(() => {
53
- if (props.placeholder) return props.placeholder
54
- if (props.type === 'datetime') return '选择日期时间'
55
- if (props.type === 'month') return '选择月份'
56
- if (props.type === 'year') return '选择年份'
57
- return '选择日期'
58
- })
51
+ const TYPE_PLACEHOLDER: Record<string, string> = {
52
+ date: '选择日期',
53
+ datetime: '选择日期时间',
54
+ month: '选择月份',
55
+ year: '选择年份',
56
+ }
59
57
 
60
- const inner = computed(() => props.modelValue || null)
58
+ const precision = computed(
59
+ () => TYPE_PRECISION[props.type] ?? ('day' as DateTimePrecision),
60
+ )
61
+
62
+ const placeholderText = computed(
63
+ () => props.placeholder || TYPE_PLACEHOLDER[props.type] || '选择日期',
64
+ )
61
65
 
62
66
  function onUpdate(v: string | null) {
63
67
  const out = v || ''
@@ -2,36 +2,35 @@
2
2
  <div class="vm-date-range" :class="{ 'is-disabled': disabled }">
3
3
  <VmDatetimeField
4
4
  class="vm-date-range__field"
5
- :model-value="props.modelValue?.[0] ?? null"
5
+ :model-value="modelValue?.[0] ?? null"
6
6
  :precision="precision"
7
7
  :placeholder="startPlaceholder"
8
8
  :disabled="disabled"
9
9
  @update:model-value="(v) => set(0, v)"
10
- @change="(v) => set(0, v)"
11
10
  />
12
11
  <span class="vm-date-range__sep">-</span>
13
12
  <VmDatetimeField
14
13
  class="vm-date-range__field"
15
- :model-value="props.modelValue?.[1] ?? null"
14
+ :model-value="modelValue?.[1] ?? null"
16
15
  :precision="precision"
17
16
  :placeholder="endPlaceholder"
18
17
  :disabled="disabled"
19
18
  @update:model-value="(v) => set(1, v)"
20
- @change="(v) => set(1, v)"
21
19
  />
22
20
  </div>
23
21
  </template>
24
22
 
25
23
  <script setup lang="ts">
26
- defineOptions({ name: 'vm-date-range' })
27
-
28
24
  import VmDatetimeField from './vm-datetime-field.vue'
25
+ import type { DateTimePrecision } from '../../../shared/datetime-picker'
26
+
27
+ defineOptions({ name: 'vm-date-range' })
29
28
 
30
29
  const props = withDefaults(
31
30
  defineProps<{
32
31
  modelValue?: Array<string | null>
33
- /** 时间精度:year | month | day | hour | minute | second */
34
- precision?: 'year' | 'month' | 'day' | 'hour' | 'minute' | 'second'
32
+ /** year | month | day | datetime */
33
+ precision?: DateTimePrecision
35
34
  startPlaceholder?: string
36
35
  endPlaceholder?: string
37
36
  disabled?: boolean
@@ -65,7 +64,6 @@ function set(idx: 0 | 1, v: string | null) {
65
64
  box-sizing: border-box;
66
65
  width: 100%;
67
66
  align-items: center;
68
- gap: 0;
69
67
 
70
68
  &.is-disabled {
71
69
  opacity: 0.55;
@@ -79,12 +77,11 @@ function set(idx: 0 | 1, v: string | null) {
79
77
  }
80
78
 
81
79
  .vm-date-range__sep {
82
- flex: 0 0 auto;
80
+ flex: none;
83
81
  padding: 0 8px;
84
82
  color: var(--muted-foreground, #94a3b8);
85
83
  font-size: 13px;
86
84
  font-weight: 600;
87
- line-height: 1;
88
85
  user-select: none;
89
86
  }
90
87
  </style>