diff --git a/packages/uni-app-plus/dist/index.v3.js b/packages/uni-app-plus/dist/index.v3.js index 3a1c2c56297632f4f386433b70619001ba73e5c4..cbb9bfea2801112b135b27081b220c382eb030da 100644 --- a/packages/uni-app-plus/dist/index.v3.js +++ b/packages/uni-app-plus/dist/index.v3.js @@ -7681,7 +7681,7 @@ var serviceContext = (function () { return webview } - function initWebview (webview, routeOptions) { + function initWebview (webview, routeOptions, url = '') { // 首页或非 nvue 页面 if (webview.id === '1' || !routeOptions.meta.isNVue) { const webviewStyle = parseWebviewStyle( @@ -7689,6 +7689,17 @@ var serviceContext = (function () { '', routeOptions ); + if (url) { + const part = url.split('?'); + webviewStyle.debugRefresh = { + isTab: routeOptions.meta.isTabBar, + arguments: JSON.stringify({ + path: part[0].substr(1), + query: part[1] || '' + }) + }; + } + if (process.env.NODE_ENV !== 'production') { console.log(`[uni-app] updateWebview`, webviewStyle); } @@ -7881,7 +7892,8 @@ var serviceContext = (function () { /** * 首页需要主动registerPage,二级页面路由跳转时registerPage */ - function registerPage ({ + function registerPage ({ + url, path, query, openType, @@ -7920,7 +7932,7 @@ var serviceContext = (function () { console.log(`[uni-app] registerPage`, path, webview.id); } - initWebview(webview, routeOptions); + initWebview(webview, routeOptions, url); const route = path.slice(1); @@ -7986,6 +7998,7 @@ var serviceContext = (function () { } function _navigateTo ({ + url, path, query, animationType, @@ -7998,6 +8011,7 @@ var serviceContext = (function () { showWebview( registerPage({ + url, path, query, openType: 'navigate' @@ -8020,18 +8034,19 @@ var serviceContext = (function () { animationDuration }, callbackId) { const urls = url.split('?'); - const path = urls[0]; - const routeStyles = __uniRoutes.find(route => route.path === path).window; - const globalStyle = __uniConfig.window; - if (!animationType) { - animationType = routeStyles.animationType || globalStyle.animationType || ANI_SHOW; - } - if (!animationDuration) { - animationDuration = routeStyles.animationDuration || globalStyle.animationDuration || ANI_DURATION; + const path = urls[0]; + const routeStyles = __uniRoutes.find(route => route.path === path).window; + const globalStyle = __uniConfig.window; + if (!animationType) { + animationType = routeStyles.animationType || globalStyle.animationType || ANI_SHOW; + } + if (!animationDuration) { + animationDuration = routeStyles.animationDuration || globalStyle.animationDuration || ANI_DURATION; } const query = parseQuery(urls[1] || ''); navigate(path, function () { _navigateTo({ + url, path, query, animationType, @@ -8041,6 +8056,7 @@ var serviceContext = (function () { } function _reLaunch ({ + url, path, query }, callbackId) { @@ -8054,6 +8070,7 @@ var serviceContext = (function () { showWebview( registerPage({ + url, path, query, openType: 'reLaunch' @@ -8082,6 +8099,7 @@ var serviceContext = (function () { const query = parseQuery(urls[1] || ''); navigate(path, function () { _reLaunch({ + url, path, query }, callbackId); @@ -8089,6 +8107,7 @@ var serviceContext = (function () { } function _redirectTo ({ + url, path, query }, callbackId) { @@ -8099,6 +8118,7 @@ var serviceContext = (function () { showWebview( registerPage({ + url, path, query, openType: 'redirect' @@ -8123,6 +8143,7 @@ var serviceContext = (function () { const query = parseQuery(urls[1] || ''); navigate(path, function () { _redirectTo({ + url, path, query }, callbackId); @@ -8130,6 +8151,7 @@ var serviceContext = (function () { } function _switchTab ({ + url, path, from }, callbackId) { @@ -8180,6 +8202,7 @@ var serviceContext = (function () { tabBarPage.$getAppWebview().show('none'); } else { return showWebview(registerPage({ + url, path, query: {}, openType: 'switchTab' @@ -8205,6 +8228,7 @@ var serviceContext = (function () { const path = url.split('?')[0]; navigate(path, function () { _switchTab({ + url, path, from }, callbackId); @@ -9451,10 +9475,12 @@ var serviceContext = (function () { ]; var tempCanvas; - function getTempCanvas () { + function getTempCanvas (width = 0, height = 0) { if (!tempCanvas) { tempCanvas = document.createElement('canvas'); } + tempCanvas.width = width; + tempCanvas.height = height; return tempCanvas } @@ -11771,7 +11797,7 @@ var serviceContext = (function () { const navigateType = routeOptions.meta.isTabBar ? 'switchTab' : 'navigateTo'; process.env.NODE_ENV !== 'production' && perf(`${entryPagePath} navigateTo`); return uni[navigateType]({ - url: entryPagePath, + url: entryPagePath + (__uniConfig.entryPageQuery || ''), openType: 'appLaunch' }) } @@ -12003,28 +12029,39 @@ var serviceContext = (function () { }); } - function initHotReload () { - const reloadUrl = weex.config.reloadUrl; - if (!reloadUrl) { + function initEntryPage () { + const argsJsonStr = plus.runtime.arguments; + if (!argsJsonStr) { return } - if (reloadUrl === __uniConfig.entryPagePath) { + + let entryPagePath; + let entryPageQuery; + + try { + const args = JSON.parse(argsJsonStr); + entryPagePath = args.path || args.pathName; + entryPageQuery = (args.query ? ('?' + args.query) : ''); + } catch (e) {} + if (!entryPagePath || entryPagePath === __uniConfig.entryPagePath) { return } - const reloadPath = '/' + reloadUrl; - const routeOptions = __uniRoutes.find(route => route.path === reloadPath); + + const entryRoute = '/' + entryPagePath; + const routeOptions = __uniRoutes.find(route => route.path === entryRoute); if (!routeOptions) { return } - if (routeOptions.meta.isNVue) { // 暂不处理 nvue - return - } + if (!routeOptions.meta.isTabBar) { __uniConfig.realEntryPagePath = __uniConfig.realEntryPagePath || __uniConfig.entryPagePath; } - __uniConfig.entryPagePath = reloadUrl; + + __uniConfig.entryPagePath = entryPagePath; + __uniConfig.entryPageQuery = entryPageQuery; + if (process.env.NODE_ENV !== 'production') { - console.log(`[uni-app] reloadUrl(${reloadUrl})`); + console.log(`[uni-app] entryPagePath(${entryPagePath + entryPageQuery})`); } } @@ -12046,7 +12083,7 @@ var serviceContext = (function () { getCurrentPages: getCurrentPages$1 }); - initHotReload(); + initEntryPage(); initTabBar(); diff --git a/packages/uni-migration/lib/index.js b/packages/uni-migration/lib/index.js index 0189efc0cd32c3150174507b3b2d79ea5e8f305e..06183ec3452a2d70090444c095805a32bdd98294 100644 --- a/packages/uni-migration/lib/index.js +++ b/packages/uni-migration/lib/index.js @@ -39,7 +39,7 @@ module.exports = function migrate(input, out, options = {}) { ) ) { options.silent !== true && console.log(`copy: ${dest}`) - fs.copySync(src, dest) + src !== dest && fs.copySync(src, dest) } } else { options.silent !== true && console.log(`write: ${path.resolve(out, asset.path)}`) diff --git a/packages/vue-cli-plugin-uni/lib/app-plus/index.js b/packages/vue-cli-plugin-uni/lib/app-plus/index.js index e76c3c2a93cdfa0501f2e35b6ccec684093a8207..fff8e1686de6fd5dcd523d649550d0a67908a1e3 100644 --- a/packages/vue-cli-plugin-uni/lib/app-plus/index.js +++ b/packages/vue-cli-plugin-uni/lib/app-plus/index.js @@ -89,13 +89,6 @@ const v3 = { loader: path.resolve(__dirname, '../../packages/webpack-uni-app-loader/view/script') }) - // view 层 renderjs - // rules.push({ - // resourceQuery: [/lang=renderjs/, /blockType=renderjs/], - // use: [{ - // loader: path.resolve(__dirname, '../../packages/webpack-uni-app-loader/view/renderjs') - // }] - // }) } scriptLoaders.push({ loader: path.resolve(__dirname, diff --git a/packages/vue-cli-plugin-uni/lib/vue-loader.js b/packages/vue-cli-plugin-uni/lib/vue-loader.js index fdb07275ec9ec575218ad2ec8ecb567bf55874ff..b58ea411c6103b466b37c8a391e6f0f61a48fd4e 100644 --- a/packages/vue-cli-plugin-uni/lib/vue-loader.js +++ b/packages/vue-cli-plugin-uni/lib/vue-loader.js @@ -28,6 +28,7 @@ module.exports = function modifyVueLoader (webpackConfig, compilerOptions, api) .use('vue-loader') .loader(require.resolve('@dcloudio/vue-cli-plugin-uni/packages/vue-loader')) .tap(options => Object.assign(options, { + isH5: process.env.UNI_PLATFORM === 'h5', compiler: getPlatformCompiler(), compilerOptions: Object.assign({ isUnaryTag, @@ -35,11 +36,11 @@ module.exports = function modifyVueLoader (webpackConfig, compilerOptions, api) }, compilerOptions) }, cacheConfig)) .end() - // .use('uniapp-custom-block-loader') - // .loader(require.resolve('@dcloudio/vue-cli-plugin-uni/packages/webpack-custom-block-loader')) - // .options({ - // compiler: getPlatformCompiler() - // }) + // .use('uniapp-custom-block-loader') + // .loader(require.resolve('@dcloudio/vue-cli-plugin-uni/packages/webpack-custom-block-loader')) + // .options({ + // compiler: getPlatformCompiler() + // }) // h5 框架需要使用 scoped 样式,其他平台编译时识别是否 nvue 文件且注入 flex 相关样式 if (process.env.UNI_PLATFORM === 'h5') { diff --git a/packages/vue-cli-plugin-uni/packages/@vue/component-compiler-utils/dist/parseCustomBlocks.js b/packages/vue-cli-plugin-uni/packages/@vue/component-compiler-utils/dist/parseCustomBlocks.js index ffea1534db8472d1c7cdb48a0c1a9d1148f12469..a474d024a4c28f60f250d57b685bf9855e6dea0a 100644 --- a/packages/vue-cli-plugin-uni/packages/@vue/component-compiler-utils/dist/parseCustomBlocks.js +++ b/packages/vue-cli-plugin-uni/packages/@vue/component-compiler-utils/dist/parseCustomBlocks.js @@ -1,10 +1,22 @@ const { getPlatformFilterTag, - normalizeNodeModules + normalizeNodeModules, + jsPreprocessOptions } = require('@dcloudio/uni-cli-shared/lib/platform') +const preprocessor = require('@dcloudio/vue-cli-plugin-uni/packages/webpack-preprocess-loader/preprocess') + const FILTER_TAG = getPlatformFilterTag() +function preprocessBlock(block) { + if (block.content) { + block.content = preprocessor.preprocess(block.content, jsPreprocessOptions.context, { + type: jsPreprocessOptions.type + }).trim() + } + return block +} + module.exports = function parseCustomBlocks(descriptor, options) { if (!descriptor.template || !FILTER_TAG || options.isAppNVue) { @@ -23,7 +35,7 @@ module.exports = function parseCustomBlocks(descriptor, options) { block.attrs.lang === FILTER_TAG ) ) { - modules[block.attrs.module] = block + modules[block.attrs.module] = preprocessBlock(block) return true } if ( // renderjs @@ -33,7 +45,7 @@ module.exports = function parseCustomBlocks(descriptor, options) { block.attrs.lang === 'renderjs' ) ) { - descriptor.renderjs = block + descriptor.renderjs = preprocessBlock(block) modules[block.attrs.module] = Object.assign({}, block, { content: '' }) diff --git a/packages/vue-cli-plugin-uni/packages/vue-loader/lib/index.js b/packages/vue-cli-plugin-uni/packages/vue-loader/lib/index.js index ec1f3eb81be615c5f7c9f877997e739ee52cc9f7..a8f3b870245f05c786a7325edbeae6c720773e4f 100644 --- a/packages/vue-cli-plugin-uni/packages/vue-loader/lib/index.js +++ b/packages/vue-cli-plugin-uni/packages/vue-loader/lib/index.js @@ -142,7 +142,7 @@ module.exports = function (source) { } let renderjsImport = `var renderjs` - if(options.isAppView && descriptor.renderjs){ + if((options.isAppView || options.isH5) && descriptor.renderjs){ const src = descriptor.renderjs.src || resourcePath const attrsQuery = attrsToQuery(descriptor.renderjs.attrs, 'js') const query = `?vue&type=renderjs${attrsQuery}${inheritQuery}` diff --git a/packages/webpack-uni-pages-loader/lib/platforms/app-plus/index.v3.js b/packages/webpack-uni-pages-loader/lib/platforms/app-plus/index.v3.js index 7565028e1eb84e4ae78a91880a0f564010248ca3..a01b967d78cdbdf1029e3892d692ca07d256a3f8 100644 --- a/packages/webpack-uni-pages-loader/lib/platforms/app-plus/index.v3.js +++ b/packages/webpack-uni-pages-loader/lib/platforms/app-plus/index.v3.js @@ -33,8 +33,10 @@ function parseEntryPagePath (appJson, manifestJson) { try { const args = JSON.parse(argsJsonStr) const pathName = args.path || args.pathName + const entryPageQuery = (args.query ? ('?' + args.query) : '') if (pathName && appJson.pages[0] !== pathName) { appJson.entryPagePath = pathName + appJson.entryPageQuery = entryPageQuery if (!isTabBarPage(pathName, getTabBarPages(appJson))) { appJson.realEntryPagePath = appJson.pages[0] } @@ -83,7 +85,7 @@ module.exports = function (appJson, manifestJson, { if (appJson.page[appJson.entryPagePath].nvue) { // 首页是 nvue manifestJson.launch_path = '' // 首页地址为空 manifestJson.plus.launchwebview.uniNView = { - path: appJson.entryPagePath + path: appJson.entryPagePath + '.js' + (appJson.entryPageQuery || '') } if (manifestJson.plus.tabBar) { manifestJson.plus.tabBar.child = ['lauchwebview'] @@ -100,4 +102,4 @@ module.exports = function (appJson, manifestJson, { manifest.content = JSON.stringify(manifest.content) delete appJson.nvue return [manifest, definePages(appJson), appConfigService(appJson)] -} +} diff --git a/src/platforms/app-plus/service/api/route/navigate-to.js b/src/platforms/app-plus/service/api/route/navigate-to.js index d7523f44b41a023dd0fd1d41d8135deef56ef14a..1ff60f4dc77eb2dd792fe9cbf46931ec57c5f102 100644 --- a/src/platforms/app-plus/service/api/route/navigate-to.js +++ b/src/platforms/app-plus/service/api/route/navigate-to.js @@ -1,7 +1,7 @@ import { parseQuery -} from 'uni-shared' - +} from 'uni-shared' + import { ANI_SHOW, ANI_DURATION @@ -25,6 +25,7 @@ import { } from '../../framework/navigator' function _navigateTo ({ + url, path, query, animationType, @@ -37,6 +38,7 @@ function _navigateTo ({ showWebview( registerPage({ + url, path, query, openType: 'navigate' @@ -59,22 +61,23 @@ export function navigateTo ({ animationDuration }, callbackId) { const urls = url.split('?') - const path = urls[0] - const routeStyles = __uniRoutes.find(route => route.path === path).window - const globalStyle = __uniConfig.window - if (!animationType) { - animationType = routeStyles.animationType || globalStyle.animationType || ANI_SHOW - } - if (!animationDuration) { - animationDuration = routeStyles.animationDuration || globalStyle.animationDuration || ANI_DURATION + const path = urls[0] + const routeStyles = __uniRoutes.find(route => route.path === path).window + const globalStyle = __uniConfig.window + if (!animationType) { + animationType = routeStyles.animationType || globalStyle.animationType || ANI_SHOW + } + if (!animationDuration) { + animationDuration = routeStyles.animationDuration || globalStyle.animationDuration || ANI_DURATION } const query = parseQuery(urls[1] || '') navigate(path, function () { _navigateTo({ + url, path, query, animationType, animationDuration }, callbackId) }, openType === 'appLaunch') -} +} diff --git a/src/platforms/app-plus/service/api/route/re-launch.js b/src/platforms/app-plus/service/api/route/re-launch.js index 272d93408b636ca280221198ed04024e94c00052..7793375fb2402ca5b04c3a00f763126431ac9961 100644 --- a/src/platforms/app-plus/service/api/route/re-launch.js +++ b/src/platforms/app-plus/service/api/route/re-launch.js @@ -22,6 +22,7 @@ import { } from '../../framework/navigator' function _reLaunch ({ + url, path, query }, callbackId) { @@ -35,6 +36,7 @@ function _reLaunch ({ showWebview( registerPage({ + url, path, query, openType: 'reLaunch' @@ -63,6 +65,7 @@ export function reLaunch ({ const query = parseQuery(urls[1] || '') navigate(path, function () { _reLaunch({ + url, path, query }, callbackId) diff --git a/src/platforms/app-plus/service/api/route/redirect-to.js b/src/platforms/app-plus/service/api/route/redirect-to.js index 850c8a55582a142da322c6854935c33150db833a..ade666e2352f96c4f44badd833b13c5ce7b889ea 100644 --- a/src/platforms/app-plus/service/api/route/redirect-to.js +++ b/src/platforms/app-plus/service/api/route/redirect-to.js @@ -20,6 +20,7 @@ import { } from '../../framework/navigator' function _redirectTo ({ + url, path, query }, callbackId) { @@ -30,6 +31,7 @@ function _redirectTo ({ showWebview( registerPage({ + url, path, query, openType: 'redirect' @@ -54,6 +56,7 @@ export function redirectTo ({ const query = parseQuery(urls[1] || '') navigate(path, function () { _redirectTo({ + url, path, query }, callbackId) diff --git a/src/platforms/app-plus/service/api/route/switch-tab.js b/src/platforms/app-plus/service/api/route/switch-tab.js index bc23f900661a36a04ae4f53d2ad255559573a023..9bcea79f5aa7592d4dd1903233a983530f5f8337 100644 --- a/src/platforms/app-plus/service/api/route/switch-tab.js +++ b/src/platforms/app-plus/service/api/route/switch-tab.js @@ -23,6 +23,7 @@ import { import tabBar from '../../framework/tab-bar' function _switchTab ({ + url, path, from }, callbackId) { @@ -73,6 +74,7 @@ function _switchTab ({ tabBarPage.$getAppWebview().show('none') } else { return showWebview(registerPage({ + url, path, query: {}, openType: 'switchTab' @@ -98,8 +100,9 @@ export function switchTab ({ const path = url.split('?')[0] navigate(path, function () { _switchTab({ + url, path, from }, callbackId) }, openType === 'appLaunch') -} +} diff --git a/src/platforms/app-plus/service/framework/app.js b/src/platforms/app-plus/service/framework/app.js index bc960e1aa77d205990e2af6cde8c5d802387b713..85eed95b2abc54f5889c0f3cf27ef2cd5e949e75 100644 --- a/src/platforms/app-plus/service/framework/app.js +++ b/src/platforms/app-plus/service/framework/app.js @@ -140,28 +140,39 @@ function initTabBar () { }) } -function initHotReload () { - const reloadUrl = weex.config.reloadUrl - if (!reloadUrl) { +function initEntryPage () { + const argsJsonStr = plus.runtime.arguments + if (!argsJsonStr) { return } - if (reloadUrl === __uniConfig.entryPagePath) { + + let entryPagePath + let entryPageQuery + + try { + const args = JSON.parse(argsJsonStr) + entryPagePath = args.path || args.pathName + entryPageQuery = (args.query ? ('?' + args.query) : '') + } catch (e) {} + if (!entryPagePath || entryPagePath === __uniConfig.entryPagePath) { return } - const reloadPath = '/' + reloadUrl - const routeOptions = __uniRoutes.find(route => route.path === reloadPath) + + const entryRoute = '/' + entryPagePath + const routeOptions = __uniRoutes.find(route => route.path === entryRoute) if (!routeOptions) { return } - if (routeOptions.meta.isNVue) { // 暂不处理 nvue - return - } + if (!routeOptions.meta.isTabBar) { __uniConfig.realEntryPagePath = __uniConfig.realEntryPagePath || __uniConfig.entryPagePath } - __uniConfig.entryPagePath = reloadUrl + + __uniConfig.entryPagePath = entryPagePath + __uniConfig.entryPageQuery = entryPageQuery + if (process.env.NODE_ENV !== 'production') { - console.log(`[uni-app] reloadUrl(${reloadUrl})`) + console.log(`[uni-app] entryPagePath(${entryPagePath + entryPageQuery})`) } } @@ -183,7 +194,7 @@ export function registerApp (appVm) { getCurrentPages }) - initHotReload() + initEntryPage() initTabBar() diff --git a/src/platforms/app-plus/service/framework/page.js b/src/platforms/app-plus/service/framework/page.js index f1fbe5a33433a7cdacb8d1eba3318ea19cfb02e4..843d62432e1686cce704461431fb6c89343f9392 100644 --- a/src/platforms/app-plus/service/framework/page.js +++ b/src/platforms/app-plus/service/framework/page.js @@ -24,7 +24,8 @@ export function getCurrentPages (returnAll) { /** * 首页需要主动registerPage,二级页面路由跳转时registerPage */ -export function registerPage ({ +export function registerPage ({ + url, path, query, openType, @@ -63,7 +64,7 @@ export function registerPage ({ console.log(`[uni-app] registerPage`, path, webview.id) } - initWebview(webview, routeOptions) + initWebview(webview, routeOptions, url) const route = path.slice(1) diff --git a/src/platforms/app-plus/service/framework/subscribe-handlers/on-webview-ready.js b/src/platforms/app-plus/service/framework/subscribe-handlers/on-webview-ready.js index abe1f468cc55c97c01c27fc638be6917fb1b24d3..9a53a495ed2ea559c31bb32f995b11dc0df9bd05 100644 --- a/src/platforms/app-plus/service/framework/subscribe-handlers/on-webview-ready.js +++ b/src/platforms/app-plus/service/framework/subscribe-handlers/on-webview-ready.js @@ -38,7 +38,7 @@ export default function onWebviewReady (data, pageId) { const navigateType = routeOptions.meta.isTabBar ? 'switchTab' : 'navigateTo' process.env.NODE_ENV !== 'production' && perf(`${entryPagePath} navigateTo`) return uni[navigateType]({ - url: entryPagePath, + url: entryPagePath + (__uniConfig.entryPageQuery || ''), openType: 'appLaunch' }) } diff --git a/src/platforms/app-plus/service/framework/webview/index.js b/src/platforms/app-plus/service/framework/webview/index.js index d95356fded00111d0e7819d8ab02bc03056eb613..11cb191688fde2e86a96afcbdb87db86b0339dd5 100644 --- a/src/platforms/app-plus/service/framework/webview/index.js +++ b/src/platforms/app-plus/service/framework/webview/index.js @@ -63,7 +63,7 @@ export function createWebview (path, routeOptions) { return webview } -export function initWebview (webview, routeOptions) { +export function initWebview (webview, routeOptions, url = '') { // 首页或非 nvue 页面 if (webview.id === '1' || !routeOptions.meta.isNVue) { const webviewStyle = parseWebviewStyle( @@ -71,6 +71,17 @@ export function initWebview (webview, routeOptions) { '', routeOptions ) + if (url) { + const part = url.split('?') + webviewStyle.debugRefresh = { + isTab: routeOptions.meta.isTabBar, + arguments: JSON.stringify({ + path: part[0].substr(1), + query: part[1] || '' + }) + } + } + if (process.env.NODE_ENV !== 'production') { console.log(`[uni-app] updateWebview`, webviewStyle) } diff --git a/src/platforms/h5/view/components/video/index.vue b/src/platforms/h5/view/components/video/index.vue index 1404e33580bfb7b4ff0c8c5aa19f167cc30f39a1..6e784c16fa53ef2b18966e1011ac877c17a86b2f 100644 --- a/src/platforms/h5/view/components/video/index.vue +++ b/src/platforms/h5/view/components/video/index.vue @@ -49,7 +49,7 @@ class="uni-video-control-button" @click.stop="trigger" /> -
{{ currentTime|getTime }}
+
{{ currentTime|time }}
-
{{ (duration||durationTime)|getTime }}
+
{{ (duration||durationTime)|time }}
-

{{ (duration||durationTime)|getTime }}

+

{{ (duration||durationTime)|time }}

-
{{ currentTimeNew|getTime }} / {{ durationTime|getTime }}
+
{{ currentTimeNew|time }} / {{ durationTime|time }}
0 && val < Infinity ? val : 0 + let h = Math.floor(val / 3600) + let m = Math.floor(val % 3600 / 60) + let s = Math.floor(val % 3600 % 60) h = (h < 10 ? '0' : '') + h m = (m < 10 ? '0' : '') + m s = (s < 10 ? '0' : '') + s