添加 agentation 成功
This commit is contained in:
@@ -0,0 +1,106 @@
|
||||
/**
|
||||
* API 封装:baseURL、Token、POST JSON、统一错误与 401 处理
|
||||
* 依据:backend/API.md,全部 POST,JSON,Bearer Token
|
||||
*/
|
||||
(function (global) {
|
||||
'use strict';
|
||||
|
||||
var BASE_URL = 'http://127.0.0.1:8000';
|
||||
var TOKEN_KEY = 'pm_token';
|
||||
var USER_KEY = 'pm_user';
|
||||
|
||||
function getToken() {
|
||||
try {
|
||||
return localStorage.getItem(TOKEN_KEY) || '';
|
||||
} catch (e) {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
function setToken(token) {
|
||||
try {
|
||||
if (token) localStorage.setItem(TOKEN_KEY, token);
|
||||
else localStorage.removeItem(TOKEN_KEY);
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
function getUser() {
|
||||
try {
|
||||
var raw = localStorage.getItem(USER_KEY);
|
||||
return raw ? JSON.parse(raw) : null;
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function setUser(user) {
|
||||
try {
|
||||
if (user) localStorage.setItem(USER_KEY, JSON.stringify(user));
|
||||
else localStorage.removeItem(USER_KEY);
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
function clearAuth() {
|
||||
setToken('');
|
||||
setUser(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* POST /api/xxx 请求
|
||||
* @param {string} path - 如 '/api/auth/login'
|
||||
* @param {object} body - 请求体
|
||||
* @param {boolean} [requireAuth=true] - 是否携带 Token
|
||||
* @returns {Promise<{ ok: boolean, data?: object, status?: number, message?: string }>}
|
||||
*/
|
||||
function post(path, body, requireAuth) {
|
||||
if (requireAuth === undefined) requireAuth = true;
|
||||
var url = BASE_URL + path;
|
||||
var headers = {
|
||||
'Content-Type': 'application/json',
|
||||
};
|
||||
var token = getToken();
|
||||
if (requireAuth && token) {
|
||||
headers['Authorization'] = 'Bearer ' + token;
|
||||
}
|
||||
return fetch(url, {
|
||||
method: 'POST',
|
||||
headers: headers,
|
||||
body: JSON.stringify(body || {}),
|
||||
})
|
||||
.then(function (res) {
|
||||
return res.text().then(function (text) {
|
||||
var data = null;
|
||||
try {
|
||||
data = text ? JSON.parse(text) : null;
|
||||
} catch (e) {
|
||||
data = null;
|
||||
}
|
||||
if (res.status === 401) {
|
||||
clearAuth();
|
||||
if (typeof global.onAuthRequired === 'function') {
|
||||
global.onAuthRequired();
|
||||
}
|
||||
return { ok: false, status: 401, message: data && data.message ? data.message : '未登录' };
|
||||
}
|
||||
if (!res.ok) {
|
||||
var msg = (data && data.message) || res.statusText || '请求失败';
|
||||
return { ok: false, status: res.status, data: data, message: msg };
|
||||
}
|
||||
return { ok: true, data: data };
|
||||
});
|
||||
})
|
||||
.catch(function (err) {
|
||||
return { ok: false, message: err && err.message ? err.message : '网络错误' };
|
||||
});
|
||||
}
|
||||
|
||||
global.API = {
|
||||
BASE_URL: BASE_URL,
|
||||
getToken: getToken,
|
||||
setToken: setToken,
|
||||
getUser: getUser,
|
||||
setUser: setUser,
|
||||
clearAuth: clearAuth,
|
||||
post: post,
|
||||
};
|
||||
})(typeof window !== 'undefined' ? window : this);
|
||||
@@ -0,0 +1,407 @@
|
||||
/**
|
||||
* 项目管理系统前端(依据产品文档、API 文档、交互文档)
|
||||
* 对接 http://127.0.0.1:8000,登录 / 列表 / 详情 / 新建 / 保存 / 操作日志
|
||||
*/
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
var PAGE_SIZE = 20;
|
||||
var currentPage = 1;
|
||||
var totalCount = 0;
|
||||
var currentProjectId = null;
|
||||
|
||||
var viewLogin = document.getElementById('view-login');
|
||||
var appMain = document.getElementById('appMain');
|
||||
var loginForm = document.getElementById('loginForm');
|
||||
var loginError = document.getElementById('loginError');
|
||||
var btnLoginSubmit = document.getElementById('btnLoginSubmit');
|
||||
var btnLogout = document.getElementById('btnLogout');
|
||||
var userInfo = document.getElementById('userInfo');
|
||||
var btnNewProject = document.getElementById('btnNewProject');
|
||||
var navList = document.getElementById('navList');
|
||||
var viewList = document.getElementById('view-list');
|
||||
var viewDetail = document.getElementById('view-detail');
|
||||
var searchType = document.getElementById('searchType');
|
||||
var searchKeyword = document.getElementById('searchKeyword');
|
||||
var btnSearch = document.getElementById('btnSearch');
|
||||
var filterProgress = document.getElementById('filterProgress');
|
||||
var filterCost = document.getElementById('filterCost');
|
||||
var dateFilterType = document.getElementById('dateFilterType');
|
||||
var dateFrom = document.getElementById('dateFrom');
|
||||
var dateTo = document.getElementById('dateTo');
|
||||
var dateAbnormal = document.getElementById('dateAbnormal');
|
||||
var listLoading = document.getElementById('listLoading');
|
||||
var listEmpty = document.getElementById('listEmpty');
|
||||
var projectTable = document.getElementById('projectTable');
|
||||
var projectTableBody = document.getElementById('projectTableBody');
|
||||
var paginationInfo = document.getElementById('paginationInfo');
|
||||
var btnPrev = document.getElementById('btnPrev');
|
||||
var btnNext = document.getElementById('btnNext');
|
||||
var btnBack = document.getElementById('btnBack');
|
||||
var detailTitle = document.getElementById('detailTitle');
|
||||
var detailLoading = document.getElementById('detailLoading');
|
||||
var detailContent = document.getElementById('detailContent');
|
||||
var btnViewLog = document.getElementById('btnViewLog');
|
||||
var btnSave = document.getElementById('btnSave');
|
||||
var logOverlay = document.getElementById('logOverlay');
|
||||
var logDrawer = document.getElementById('logDrawer');
|
||||
var logDrawerClose = document.getElementById('logDrawerClose');
|
||||
var logLoading = document.getElementById('logLoading');
|
||||
var logEmpty = document.getElementById('logEmpty');
|
||||
var logList = document.getElementById('logList');
|
||||
var toast = document.getElementById('toast');
|
||||
|
||||
function showLogin() {
|
||||
if (viewLogin) viewLogin.classList.remove('hidden');
|
||||
if (appMain) appMain.style.display = 'none';
|
||||
}
|
||||
|
||||
function showApp() {
|
||||
if (viewLogin) viewLogin.classList.add('hidden');
|
||||
if (appMain) appMain.style.display = 'flex';
|
||||
var u = window.API && window.API.getUser ? window.API.getUser() : null;
|
||||
if (userInfo && u) userInfo.textContent = (u.displayName || u.username || '') + ' · ' + (u.role || '');
|
||||
updateNewProjectVisibility();
|
||||
loadList();
|
||||
}
|
||||
|
||||
window.onAuthRequired = function () {
|
||||
showLogin();
|
||||
};
|
||||
|
||||
function isMarketRole() {
|
||||
var u = window.API && window.API.getUser ? window.API.getUser() : null;
|
||||
return u && u.role === '市场部';
|
||||
}
|
||||
|
||||
function updateNewProjectVisibility() {
|
||||
if (btnNewProject) btnNewProject.style.display = isMarketRole() ? '' : 'none';
|
||||
}
|
||||
|
||||
function showToast(message, type) {
|
||||
if (!toast) return;
|
||||
toast.textContent = message;
|
||||
toast.className = 'toast visible' + (type ? ' ' + type : '');
|
||||
clearTimeout(toast._tid);
|
||||
toast._tid = setTimeout(function () {
|
||||
toast.classList.remove('visible');
|
||||
}, 2500);
|
||||
}
|
||||
|
||||
function showList() {
|
||||
if (viewList) viewList.classList.add('active');
|
||||
if (viewDetail) viewDetail.classList.remove('active');
|
||||
if (navList) navList.classList.add('active');
|
||||
document.querySelectorAll('.nav-item').forEach(function (n) { n.classList.remove('active'); });
|
||||
if (navList) navList.classList.add('active');
|
||||
}
|
||||
|
||||
function showDetail(projectId) {
|
||||
currentProjectId = projectId;
|
||||
if (viewList) viewList.classList.remove('active');
|
||||
if (viewDetail) viewDetail.classList.add('active');
|
||||
document.querySelectorAll('.nav-item').forEach(function (n) { n.classList.remove('active'); });
|
||||
if (detailTitle) detailTitle.textContent = projectId ? '项目详情' : '新建项目';
|
||||
if (detailLoading) detailLoading.style.display = 'block';
|
||||
if (detailContent) detailContent.style.display = 'none';
|
||||
|
||||
if (projectId) {
|
||||
window.API.post('/api/projects/detail', { id: projectId }).then(function (res) {
|
||||
if (detailLoading) detailLoading.style.display = 'none';
|
||||
if (detailContent) detailContent.style.display = 'block';
|
||||
if (res.ok && res.data) {
|
||||
fillDetailForm(res.data);
|
||||
} else {
|
||||
showToast(res.message || '加载失败', 'error');
|
||||
}
|
||||
});
|
||||
} else {
|
||||
if (detailLoading) detailLoading.style.display = 'none';
|
||||
if (detailContent) detailContent.style.display = 'block';
|
||||
clearDetailForm();
|
||||
}
|
||||
}
|
||||
|
||||
function getFormDataBySection(sectionName) {
|
||||
var panel = document.querySelector('.tab-panel[id="panel-' + sectionName + '"]');
|
||||
if (!panel) return {};
|
||||
var grid = panel.querySelector('[data-section="' + sectionName + '"]');
|
||||
if (!grid) return {};
|
||||
var obj = {};
|
||||
grid.querySelectorAll('[data-field]').forEach(function (el) {
|
||||
var key = el.getAttribute('data-field');
|
||||
if (!key) return;
|
||||
var val = el.value;
|
||||
if (el.type === 'number' && val !== '') val = Number(val);
|
||||
if (val !== '' && val !== undefined) obj[key] = val;
|
||||
});
|
||||
return obj;
|
||||
}
|
||||
|
||||
function fillDetailForm(project) {
|
||||
function setSection(sectionName, data) {
|
||||
if (!data) return;
|
||||
var panel = document.querySelector('.tab-panel[id="panel-' + sectionName + '"]');
|
||||
if (!panel) return;
|
||||
var grid = panel.querySelector('[data-section="' + sectionName + '"]');
|
||||
if (!grid) return;
|
||||
grid.querySelectorAll('[data-field]').forEach(function (el) {
|
||||
var key = el.getAttribute('data-field');
|
||||
if (!key || data[key] === undefined) return;
|
||||
var v = data[key];
|
||||
if (v !== null && v !== undefined) el.value = v;
|
||||
else el.value = '';
|
||||
});
|
||||
}
|
||||
setSection('contract', project.contract);
|
||||
setSection('costControl', project.costControl);
|
||||
setSection('receivable', project.receivable);
|
||||
setSection('payable', project.payable);
|
||||
setSection('other', project.other);
|
||||
}
|
||||
|
||||
function clearDetailForm() {
|
||||
['contract', 'costControl', 'receivable', 'payable', 'other'].forEach(function (sectionName) {
|
||||
var panel = document.querySelector('.tab-panel[id="panel-' + sectionName + '"]');
|
||||
if (!panel) return;
|
||||
var grid = panel.querySelector('[data-section="' + sectionName + '"]');
|
||||
if (!grid) return;
|
||||
grid.querySelectorAll('input, select, textarea').forEach(function (el) {
|
||||
if (el.type === 'checkbox' || el.type === 'radio') el.checked = false;
|
||||
else el.value = '';
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function collectPayload() {
|
||||
var contract = getFormDataBySection('contract');
|
||||
var costControl = getFormDataBySection('costControl');
|
||||
var receivable = getFormDataBySection('receivable');
|
||||
var payable = getFormDataBySection('payable');
|
||||
var other = getFormDataBySection('other');
|
||||
return { contract: contract, costControl: costControl, receivable: receivable, payable: payable, other: other };
|
||||
}
|
||||
|
||||
function loadList() {
|
||||
if (listLoading) listLoading.style.display = 'block';
|
||||
if (listEmpty) listEmpty.style.display = 'none';
|
||||
if (projectTable) projectTable.style.visibility = 'hidden';
|
||||
|
||||
var body = {
|
||||
page: currentPage,
|
||||
pageSize: PAGE_SIZE,
|
||||
searchType: searchType && searchType.value ? searchType.value : undefined,
|
||||
keyword: searchKeyword && searchKeyword.value ? searchKeyword.value.trim() : undefined,
|
||||
progress: filterProgress && filterProgress.value ? filterProgress.value : undefined,
|
||||
cost: filterCost && filterCost.value ? filterCost.value : undefined,
|
||||
dateFilterType: dateFilterType && dateFilterType.value ? dateFilterType.value : undefined,
|
||||
dateFrom: dateFrom && dateFrom.value ? dateFrom.value : undefined,
|
||||
dateTo: dateTo && dateTo.value ? dateTo.value : undefined,
|
||||
dateAbnormal: dateAbnormal && dateAbnormal.checked ? true : undefined,
|
||||
};
|
||||
if (!body.keyword) body.searchType = undefined;
|
||||
if (!body.dateFilterType) body.dateFrom = body.dateTo = undefined;
|
||||
|
||||
window.API.post('/api/projects/list', body).then(function (res) {
|
||||
if (listLoading) listLoading.style.display = 'none';
|
||||
if (!res.ok) {
|
||||
showToast(res.message || '加载失败', 'error');
|
||||
if (listEmpty) listEmpty.style.display = 'flex';
|
||||
if (listEmpty) listEmpty.querySelector('p').textContent = res.message || '加载失败';
|
||||
return;
|
||||
}
|
||||
var list = (res.data && res.data.list) || [];
|
||||
totalCount = (res.data && res.data.total) || 0;
|
||||
if (list.length === 0) {
|
||||
if (listEmpty) listEmpty.style.display = 'flex';
|
||||
if (listEmpty) listEmpty.querySelector('p').textContent = '暂无项目数据';
|
||||
if (projectTable) projectTable.style.visibility = 'hidden';
|
||||
} else {
|
||||
if (listEmpty) listEmpty.style.display = 'none';
|
||||
if (projectTable) projectTable.style.visibility = 'visible';
|
||||
var html = list
|
||||
.map(function (p) {
|
||||
var updatedAt = p.updatedAt ? p.updatedAt.slice(0, 10) : '—';
|
||||
return (
|
||||
'<tr>' +
|
||||
'<td>' + (p.projectName || '—') + '</td>' +
|
||||
'<td>' + (p.contractCode || '—') + '</td>' +
|
||||
'<td>' + (p.progress || '—') + '</td>' +
|
||||
'<td>' + (p.cost || '—') + '</td>' +
|
||||
'<td>' + updatedAt + '</td>' +
|
||||
'<td class="cell-actions">' +
|
||||
'<button type="button" class="link-action" data-id="' + p.id + '">查看</button> ' +
|
||||
'<button type="button" class="link-action" data-id="' + p.id + '">编辑</button>' +
|
||||
'</td>' +
|
||||
'</tr>'
|
||||
);
|
||||
})
|
||||
.join('');
|
||||
if (projectTableBody) projectTableBody.innerHTML = html;
|
||||
projectTableBody.querySelectorAll('.link-action').forEach(function (btn) {
|
||||
btn.addEventListener('click', function () {
|
||||
var id = btn.getAttribute('data-id');
|
||||
showDetail(id);
|
||||
});
|
||||
});
|
||||
}
|
||||
if (paginationInfo) paginationInfo.textContent = '共 ' + totalCount + ' 条';
|
||||
if (btnPrev) btnPrev.disabled = currentPage <= 1;
|
||||
if (btnNext) btnNext.disabled = currentPage * PAGE_SIZE >= totalCount;
|
||||
});
|
||||
}
|
||||
|
||||
function bindTabs() {
|
||||
document.querySelectorAll('.tab').forEach(function (tab) {
|
||||
tab.addEventListener('click', function () {
|
||||
var t = tab.getAttribute('data-tab');
|
||||
document.querySelectorAll('.tab').forEach(function (x) { x.classList.remove('active'); });
|
||||
document.querySelectorAll('.tab-panel').forEach(function (p) {
|
||||
if (p.id === 'panel-' + t) p.classList.add('active');
|
||||
else p.classList.remove('active');
|
||||
});
|
||||
tab.classList.add('active');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (loginForm) {
|
||||
loginForm.addEventListener('submit', function (e) {
|
||||
e.preventDefault();
|
||||
var username = document.getElementById('loginUsername');
|
||||
var password = document.getElementById('loginPassword');
|
||||
if (!username || !password) return;
|
||||
if (loginError) loginError.style.display = 'none';
|
||||
if (btnLoginSubmit) btnLoginSubmit.disabled = true;
|
||||
|
||||
window.API.post('/api/auth/login', { username: username.value.trim(), password: password.value }, false).then(function (res) {
|
||||
if (btnLoginSubmit) btnLoginSubmit.disabled = false;
|
||||
if (res.ok && res.data) {
|
||||
window.API.setToken(res.data.token || '');
|
||||
window.API.setUser(res.data.user || null);
|
||||
showApp();
|
||||
} else {
|
||||
if (loginError) {
|
||||
loginError.textContent = res.message || '账号或密码错误';
|
||||
loginError.style.display = 'block';
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (btnLogout) {
|
||||
btnLogout.addEventListener('click', function () {
|
||||
window.API.clearAuth();
|
||||
showLogin();
|
||||
});
|
||||
}
|
||||
|
||||
if (btnSearch) btnSearch.addEventListener('click', function () { currentPage = 1; loadList(); });
|
||||
if (searchKeyword) searchKeyword.addEventListener('keydown', function (e) { if (e.key === 'Enter') { currentPage = 1; loadList(); } });
|
||||
if (filterProgress) filterProgress.addEventListener('change', function () { currentPage = 1; loadList(); });
|
||||
if (filterCost) filterCost.addEventListener('change', function () { currentPage = 1; loadList(); });
|
||||
if (dateFilterType) dateFilterType.addEventListener('change', function () { currentPage = 1; loadList(); });
|
||||
if (dateFrom) dateFrom.addEventListener('change', function () { currentPage = 1; loadList(); });
|
||||
if (dateTo) dateTo.addEventListener('change', function () { currentPage = 1; loadList(); });
|
||||
if (dateAbnormal) dateAbnormal.addEventListener('change', function () { currentPage = 1; loadList(); });
|
||||
|
||||
if (btnPrev) btnPrev.addEventListener('click', function () { if (currentPage > 1) { currentPage--; loadList(); } });
|
||||
if (btnNext) btnNext.addEventListener('click', function () { if (currentPage * PAGE_SIZE < totalCount) { currentPage++; loadList(); } });
|
||||
|
||||
if (btnNewProject) btnNewProject.addEventListener('click', function () { showDetail(null); });
|
||||
if (btnBack) btnBack.addEventListener('click', function () { showList(); loadList(); });
|
||||
if (navList) navList.addEventListener('click', function (e) { e.preventDefault(); showList(); });
|
||||
|
||||
if (btnSave) {
|
||||
btnSave.addEventListener('click', function () {
|
||||
var textSpan = btnSave.querySelector('.btn-text');
|
||||
var loadingSpan = btnSave.querySelector('.btn-loading');
|
||||
if (loadingSpan && loadingSpan.style.display === 'inline') return;
|
||||
|
||||
var payload = collectPayload();
|
||||
if (!payload.contract.contractCode || !payload.contract.projectName) {
|
||||
showToast('请填写合同编号和项目名称', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
if (textSpan) textSpan.style.display = 'none';
|
||||
if (loadingSpan) loadingSpan.style.display = 'inline';
|
||||
btnSave.disabled = true;
|
||||
|
||||
if (currentProjectId) {
|
||||
window.API.post('/api/projects/update', { id: currentProjectId, contract: payload.contract, costControl: payload.costControl, receivable: payload.receivable, payable: payload.payable, other: payload.other }).then(function (res) {
|
||||
if (textSpan) textSpan.style.display = 'inline';
|
||||
if (loadingSpan) loadingSpan.style.display = 'none';
|
||||
btnSave.disabled = false;
|
||||
if (res.ok) {
|
||||
showToast('保存成功', 'success');
|
||||
} else {
|
||||
showToast(res.message || '保存失败', 'error');
|
||||
}
|
||||
});
|
||||
} else {
|
||||
window.API.post('/api/projects/create', { contract: payload.contract, costControl: payload.costControl, receivable: payload.receivable, payable: payload.payable, other: payload.other }).then(function (res) {
|
||||
if (textSpan) textSpan.style.display = 'inline';
|
||||
if (loadingSpan) loadingSpan.style.display = 'none';
|
||||
btnSave.disabled = false;
|
||||
if (res.ok && res.data && res.data.id) {
|
||||
showToast('创建成功', 'success');
|
||||
currentProjectId = res.data.id;
|
||||
if (detailTitle) detailTitle.textContent = '项目详情';
|
||||
} else {
|
||||
showToast(res.message || '创建失败', 'error');
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function openLogDrawer() {
|
||||
if (!currentProjectId) return;
|
||||
if (logOverlay) logOverlay.classList.add('visible');
|
||||
if (logDrawer) logDrawer.classList.add('visible');
|
||||
if (logOverlay) logOverlay.setAttribute('aria-hidden', 'false');
|
||||
if (logLoading) logLoading.style.display = 'block';
|
||||
if (logEmpty) logEmpty.style.display = 'none';
|
||||
if (logList) logList.innerHTML = '';
|
||||
|
||||
window.API.post('/api/projects/logs', { id: currentProjectId, page: 1, pageSize: 20 }).then(function (res) {
|
||||
if (logLoading) logLoading.style.display = 'none';
|
||||
if (!res.ok) {
|
||||
if (logEmpty) logEmpty.querySelector('p').textContent = res.message || '加载失败';
|
||||
if (logEmpty) logEmpty.style.display = 'flex';
|
||||
return;
|
||||
}
|
||||
var list = (res.data && res.data.list) || [];
|
||||
if (list.length === 0) {
|
||||
if (logEmpty) logEmpty.style.display = 'flex';
|
||||
} else {
|
||||
logList.innerHTML = list
|
||||
.map(function (l) {
|
||||
var time = l.operatedAt ? l.operatedAt.replace('T', ' ').slice(0, 19) : '';
|
||||
return '<li class="log-item"><div class="log-meta">' + (l.operatorName || '') + ' · ' + time + '</div><div class="log-desc">' + (l.summary || '') + '</div></li>';
|
||||
})
|
||||
.join('');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function closeLogDrawer() {
|
||||
if (logOverlay) logOverlay.classList.remove('visible');
|
||||
if (logDrawer) logDrawer.classList.remove('visible');
|
||||
if (logOverlay) logOverlay.setAttribute('aria-hidden', 'true');
|
||||
}
|
||||
|
||||
if (btnViewLog) btnViewLog.addEventListener('click', openLogDrawer);
|
||||
if (logDrawerClose) logDrawerClose.addEventListener('click', closeLogDrawer);
|
||||
if (logOverlay) logOverlay.addEventListener('click', closeLogDrawer);
|
||||
|
||||
bindTabs();
|
||||
|
||||
if (window.API && window.API.getToken && window.API.getToken()) {
|
||||
showApp();
|
||||
} else {
|
||||
showLogin();
|
||||
}
|
||||
})();
|
||||
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* Music Stream landing — minimal interaction
|
||||
* Smooth scroll, play button state, CTA focus
|
||||
*/
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
document.querySelectorAll('a[href^="#"]').forEach(function (a) {
|
||||
a.addEventListener('click', function (e) {
|
||||
var id = this.getAttribute('href');
|
||||
if (id === '#') return;
|
||||
var el = document.querySelector(id);
|
||||
if (el) {
|
||||
e.preventDefault();
|
||||
el.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
var playBtn = document.querySelector('.player-btn-play');
|
||||
if (playBtn) {
|
||||
playBtn.addEventListener('click', function () {
|
||||
this.classList.toggle('is-playing');
|
||||
var label = this.getAttribute('aria-label');
|
||||
this.setAttribute('aria-label', label === 'Play' ? 'Pause' : 'Play');
|
||||
});
|
||||
}
|
||||
})();
|
||||
Reference in New Issue
Block a user