From f41efb60c75bcdd5ee31744d9c92ca97f95495f3 Mon Sep 17 00:00:00 2001 From: User Date: Fri, 6 Mar 2026 18:02:06 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=9D=E5=A7=8B=E5=8C=96=E9=A1=B9=E7=9B=AE?= =?UTF-8?q?=EF=BC=9A=E5=89=8D=E5=90=8E=E7=AB=AF=E5=88=86=E7=A6=BB=E6=9E=B6?= =?UTF-8?q?=E6=9E=84=EF=BC=8C=E5=8C=85=E5=90=AB=E7=99=BB=E5=BD=95=E6=B3=A8?= =?UTF-8?q?=E5=86=8C=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/api.js | 157 ++++++++++++ app.js | 519 ++++++++++++++++++++++++++++++++++++++ auth/login.html | 105 ++++++++ auth/login.js | 55 ++++ auth/register.html | 150 +++++++++++ auth/register.js | 74 ++++++ framework.js | 293 +++++++++++++++++++++ index.html | 199 +++++++++++++++ models/auditPermission.js | 64 +++++ models/company.js | 66 +++++ models/customer.js | 56 ++++ models/customerContact.js | 48 ++++ models/department.js | 64 +++++ models/employee.js | 82 ++++++ models/index.js | 28 ++ models/operationLog.js | 46 ++++ models/position.js | 62 +++++ 17 files changed, 2068 insertions(+) create mode 100644 api/api.js create mode 100644 app.js create mode 100644 auth/login.html create mode 100644 auth/login.js create mode 100644 auth/register.html create mode 100644 auth/register.js create mode 100644 framework.js create mode 100644 index.html create mode 100644 models/auditPermission.js create mode 100644 models/company.js create mode 100644 models/customer.js create mode 100644 models/customerContact.js create mode 100644 models/department.js create mode 100644 models/employee.js create mode 100644 models/index.js create mode 100644 models/operationLog.js create mode 100644 models/position.js diff --git a/api/api.js b/api/api.js new file mode 100644 index 0000000..8577333 --- /dev/null +++ b/api/api.js @@ -0,0 +1,157 @@ +/** + * API服务模块 + * 处理前后端通信 + */ + +const API_BASE_URL = 'http://192.168.1.101:8080/api'; // API基础路径 + +/** + * 基础请求函数 + * @param {string} url - 请求路径 + * @param {Object} options - 请求选项 + * @returns {Promise} - 返回Promise对象 + */ +async function request(url, options = {}) { + try { + // 构建完整的请求URL + const fullUrl = `${API_BASE_URL}${url}`; + + // 设置默认请求头 + const headers = { + 'Content-Type': 'application/json', + ...options.headers + }; + + // 发送请求 + const response = await fetch(fullUrl, { + ...options, + headers + }); + + // 检查响应状态 + if (!response.ok) { + const errorData = await response.json().catch(() => ({})); + throw new Error(errorData.message || `请求失败: ${response.status}`); + } + + // 解析响应数据 + return await response.json(); + } catch (error) { + console.error('API请求错误:', error); + throw error; + } +} + +/** + * 认证相关API + */ +const authApi = { + /** + * 用户登录 + * @param {Object} data - 登录数据 + * @param {string} data.mobile - 手机号 + * @param {string} data.password - 密码 + * @returns {Promise} - 返回登录结果 + */ + login: async (data) => { + return request('/auth/login', { + method: 'POST', + body: JSON.stringify(data) + }); + }, + + /** + * 用户注册 + * @param {Object} data - 注册数据 + * @param {number} data.companyId - 公司ID + * @param {number} data.deptId - 部门ID + * @param {number} data.positionId - 职位ID + * @param {string} data.empName - 姓名 + * @param {string} data.mobile - 手机号 + * @param {string} data.password - 密码 + * @returns {Promise} - 返回注册结果 + */ + register: async (data) => { + return request('/auth/register', { + method: 'POST', + body: JSON.stringify(data) + }); + } +}; + +/** + * 数据模型相关API + */ +const modelApi = { + /** + * 获取模型列表 + * @param {string} modelName - 模型名称 + * @param {Object} params - 查询参数 + * @returns {Promise} - 返回模型列表 + */ + getList: async (modelName, params = {}) => { + // 构建查询字符串 + const queryString = new URLSearchParams(params).toString(); + const url = `/models/${modelName}${queryString ? `?${queryString}` : ''}`; + return request(url); + }, + + /** + * 获取模型详情 + * @param {string} modelName - 模型名称 + * @param {number} id - 模型ID + * @returns {Promise} - 返回模型详情 + */ + getDetail: async (modelName, id) => { + return request(`/models/${modelName}/${id}`); + }, + + /** + * 创建模型 + * @param {string} modelName - 模型名称 + * @param {Object} data - 模型数据 + * @returns {Promise} - 返回创建结果 + */ + create: async (modelName, data) => { + return request(`/models/${modelName}`, { + method: 'POST', + body: JSON.stringify(data) + }); + }, + + /** + * 更新模型 + * @param {string} modelName - 模型名称 + * @param {number} id - 模型ID + * @param {Object} data - 模型数据 + * @returns {Promise} - 返回更新结果 + */ + update: async (modelName, id, data) => { + return request(`/models/${modelName}/${id}`, { + method: 'PUT', + body: JSON.stringify(data) + }); + }, + + /** + * 删除模型 + * @param {string} modelName - 模型名称 + * @param {number} id - 模型ID + * @returns {Promise} - 返回删除结果 + */ + delete: async (modelName, id) => { + return request(`/models/${modelName}/${id}`, { + method: 'DELETE' + }); + } +}; + +// 导出API服务 +const API = { + auth: authApi, + model: modelApi, + request // 导出基础请求函数,方便扩展 +}; + +// 导出为全局变量 +window.API = API; \ No newline at end of file diff --git a/app.js b/app.js new file mode 100644 index 0000000..a3e45a5 --- /dev/null +++ b/app.js @@ -0,0 +1,519 @@ +/** + * 应用示例 + * 使用简单HTML5前端框架实现页面交互 + */ + +// 等待DOM加载完成 +document.addEventListener('DOMContentLoaded', function() { + // 初始化登录状态 + initLoginStatus(); + + // 初始化路由 + initRouter(); + + // 初始化计数器组件 + initCounter(); +}); + +/** + * 初始化登录状态 + */ +function initLoginStatus() { + const currentUser = localStorage.getItem('currentUser'); + const welcomeMessage = document.getElementById('welcome-message'); + const loginLink = document.getElementById('login-link'); + const logoutLink = document.getElementById('logout-link'); + + if (currentUser) { + const user = JSON.parse(currentUser); + welcomeMessage.textContent = `欢迎,${user.emp_name} `; + loginLink.style.display = 'none'; + logoutLink.style.display = 'inline'; + } else { + welcomeMessage.textContent = ''; + loginLink.style.display = 'inline'; + logoutLink.style.display = 'none'; + } + + // 登出功能 + if (logoutLink) { + logoutLink.addEventListener('click', function(e) { + e.preventDefault(); + localStorage.removeItem('currentUser'); + window.location.reload(); + }); + } +} + +/** + * 初始化路由 + */ +function initRouter() { + // 注册路由 + Framework.router.register('home', function() { + showSection('home'); + }); + + Framework.router.register('about', function() { + showSection('about'); + }); + + Framework.router.register('counter', function() { + showSection('counter'); + }); + + Framework.router.register('models', function() { + showSection('models'); + initDataModels(); + }); + + // 初始化路由 + Framework.router.init(); +} + +/** + * 显示指定 section + * @param {string} sectionId - section ID + */ +function showSection(sectionId) { + // 隐藏所有 section + const sections = Framework.dom.queryAll('section'); + sections.forEach(section => { + section.style.display = 'none'; + }); + + // 显示指定 section + const targetSection = Framework.dom.query(`#${sectionId}`); + if (targetSection) { + targetSection.style.display = 'block'; + } +} + +/** + * 初始化计数器组件 + */ +function initCounter() { + // 初始化状态 + Framework.store.set('count', 0); + + // 获取DOM元素 + const countElement = Framework.dom.query('#count'); + const incrementButton = Framework.dom.query('#increment'); + const decrementButton = Framework.dom.query('#decrement'); + const resetButton = Framework.dom.query('#reset'); + + // 订阅状态变化 + Framework.store.subscribe(function(state) { + countElement.textContent = state.count; + }); + + // 添加事件监听器 + Framework.dom.on(incrementButton, 'click', function() { + const currentCount = Framework.store.get('count'); + Framework.store.set('count', currentCount + 1); + }); + + Framework.dom.on(decrementButton, 'click', function() { + const currentCount = Framework.store.get('count'); + Framework.store.set('count', currentCount - 1); + }); + + Framework.dom.on(resetButton, 'click', function() { + Framework.store.set('count', 0); + }); +} + +// 示例:注册一个简单的组件 +Framework.component.register('HelloComponent', function(props) { + this.props = props; + this.element = null; + + this.render = function() { + return Framework.dom.create('div', { + text: `Hello, ${this.props.name}!`, + style: { + padding: '20px', + backgroundColor: '#f0f0f0', + borderRadius: '5px', + marginTop: '20px' + } + }); + }; + + this.mount = function(container) { + this.element = this.render(); + container.appendChild(this.element); + }; + + this.update = function(newProps) { + this.props = newProps; + if (this.element) { + const parent = this.element.parentNode; + parent.removeChild(this.element); + this.element = this.render(); + parent.appendChild(this.element); + } + }; +}); + +// 示例:创建组件实例 +// const helloComponent = Framework.component.create('HelloComponent', { name: 'World' }, document.body); + +/** + * 初始化数据模型示例 + */ +function initDataModels() { + // 测试审核权限模型 + const auditPermissionDemo = Framework.dom.query('#audit-permission-demo'); + if (auditPermissionDemo) { + // 创建审核权限实例 + const auditPermission = Framework.model.AuditPermission.create({ + uuid: '12345678901234567890123456789012', + company_id: 1, + position_id: 101, + audit_type: 'order', + audit_level: 1, + audit_scope: '*', + max_audit_amount: 10000.00, + sort: 1, + status: 1, + remark: '订单初审权限' + }); + + // 展示审核权限数据 + auditPermissionDemo.innerHTML = ` +
+

审核权限详情

+

UUID: ${auditPermission.uuid}

+

公司ID: ${auditPermission.company_id}

+

岗位ID: ${auditPermission.position_id}

+

审核类型: ${auditPermission.audit_type}

+

审核层级: ${auditPermission.audit_level}

+

审核范围: ${auditPermission.audit_scope}

+

最大审核金额: ${auditPermission.max_audit_amount}

+

状态: ${auditPermission.status === 1 ? '正常' : '禁用'}

+

创建时间: ${auditPermission.create_time}

+

备注: ${auditPermission.remark}

+
+ `; + } + + // 测试公司模型 + const companyDemo = Framework.dom.query('#company-demo'); + if (companyDemo) { + // 创建公司实例 + const company = Framework.model.Company.create({ + uuid: '98765432109876543210987654321098', + company_name: '示例科技有限公司', + tenant_id: 'tenant_001', + parent_company_id: 0, + short_name: '示例科技', + industry: '互联网', + contact_mobile: '13800138000', + contact_email: 'contact@example.com', + status: 1, + remark: '这是一个示例公司' + }); + + // 展示公司数据 + companyDemo.innerHTML = ` +
+

公司详情

+

UUID: ${company.uuid}

+

公司名称: ${company.company_name}

+

租户ID: ${company.tenant_id}

+

上级公司ID: ${company.parent_company_id}

+

公司简称: ${company.short_name}

+

所属行业: ${company.industry}

+

联系电话: ${company.contact_mobile}

+

联系邮箱: ${company.contact_email}

+

状态: ${getStatusText(company.status)}

+

创建时间: ${company.create_time}

+

备注: ${company.remark}

+
+ `; + } + + // 测试客户模型 + const customerDemo = Framework.dom.query('#customer-demo'); + if (customerDemo) { + // 创建客户实例 + const customer = Framework.model.Customer.create({ + customer_id: 1, + customer_name: '张三', + create_date: '2026-01-01', + last_order_date: '2026-03-01', + last_followup_date: '2026-03-05', + followup_status: '跟进中,客户对产品有兴趣', + responsible_person: '李四', + department: '销售部', + assistant: '王五', + region: '北京市', + customer_type: '个人', + customer_level: 'A', + basic_requirements: '需要定制化服务', + specifications: '产品规格要求:中型企业级解决方案' + }); + + // 展示客户数据 + customerDemo.innerHTML = ` +
+

客户详情

+

客户ID: ${customer.customer_id}

+

客户名称: ${customer.customer_name}

+

建户日期: ${customer.create_date}

+

最后下单日期: ${customer.last_order_date}

+

最后跟进日期: ${customer.last_followup_date}

+

跟进情况: ${customer.followup_status}

+

负责人: ${customer.responsible_person}

+

部门: ${customer.department}

+

协助人: ${customer.assistant}

+

客户地区: ${customer.region}

+

客户类型: ${customer.customer_type}

+

客户等级: ${customer.customer_level}

+

基本需求: ${customer.basic_requirements}

+

规格: ${customer.specifications}

+

创建时间: ${customer.created_at}

+

更新时间: ${customer.updated_at}

+
+ `; + } + + // 测试客户联系信息模型 + const customerContactDemo = Framework.dom.query('#customer-contact-demo'); + if (customerContactDemo) { + // 创建客户联系信息实例 + const customerContact = Framework.model.CustomerContact.create({ + contact_id: 1, + customer_id: 1, + wechat_id: 'zhangsan123', + contact_name: '张三', + phone: '13800138000', + account: '张三', + account_number: '6222021234567890123', + bank: '中国工商银行', + address: '北京市朝阳区建国路88号', + company_name: '个人' + }); + + // 展示客户联系信息数据 + customerContactDemo.innerHTML = ` +
+

客户联系信息详情

+

联系ID: ${customerContact.contact_id}

+

客户ID: ${customerContact.customer_id}

+

微信号: ${customerContact.wechat_id}

+

联系人姓名: ${customerContact.contact_name}

+

电话: ${customerContact.phone}

+

账户名称: ${customerContact.account}

+

账号: ${customerContact.account_number}

+

开户行: ${customerContact.bank}

+

地址: ${customerContact.address}

+

客户公司: ${customerContact.company_name}

+

创建时间: ${customerContact.created_at}

+

更新时间: ${customerContact.updated_at}

+
+ `; + } + + // 测试部门模型 + const departmentDemo = Framework.dom.query('#department-demo'); + if (departmentDemo) { + // 创建部门实例 + const department = Framework.model.Department.create({ + id: 1, + uuid: '12345678901234567890123456789012', + company_id: 1, + dept_name: '销售部', + parent_id: 0, + dept_level: 1, + dept_code: 'SALES', + leader_id: 101, + sort: 1, + status: 1, + remark: '公司销售部门' + }); + + // 展示部门数据 + departmentDemo.innerHTML = ` +
+

部门详情

+

部门ID: ${department.id}

+

UUID: ${department.uuid}

+

公司ID: ${department.company_id}

+

部门名称: ${department.dept_name}

+

上级部门ID: ${department.parent_id}

+

部门级别: ${department.dept_level}

+

部门编码: ${department.dept_code}

+

部门负责人ID: ${department.leader_id}

+

排序号: ${department.sort}

+

状态: ${department.status === 1 ? '正常' : '禁用'}

+

创建时间: ${department.create_time}

+

备注: ${department.remark}

+
+ `; + } + + // 测试员工模型 + const employeeDemo = Framework.dom.query('#employee-demo'); + if (employeeDemo) { + // 创建员工实例 + const employee = Framework.model.Employee.create({ + id: 1, + uuid: '12345678901234567890123456789012', + company_id: 1, + dept_id: 1, + position_id: 1, + emp_name: '张三', + mobile: '13800138000', + emp_no: 'EMP001', + email: 'zhangsan@example.com', + id_card: '1101**********1234', + entry_time: '2026-01-01', + is_admin: 0, + is_leader: 1, + status: 1, + last_login_time: '2026-03-05 10:30:00', + remark: '销售部经理' + }); + + // 展示员工数据 + employeeDemo.innerHTML = ` +
+

员工详情

+

员工ID: ${employee.id}

+

UUID: ${employee.uuid}

+

公司ID: ${employee.company_id}

+

部门ID: ${employee.dept_id}

+

岗位ID: ${employee.position_id}

+

员工姓名: ${employee.emp_name}

+

手机号: ${employee.mobile}

+

员工工号: ${employee.emp_no}

+

邮箱: ${employee.email}

+

身份证号: ${employee.id_card}

+

入职时间: ${employee.entry_time}

+

是否公司管理员: ${employee.is_admin === 1 ? '是' : '否'}

+

是否部门负责人: ${employee.is_leader === 1 ? '是' : '否'}

+

状态: ${employee.status === 1 ? '正常' : employee.status === 2 ? '离职' : '禁用'}

+

最后登录时间: ${employee.last_login_time}

+

创建时间: ${employee.create_time}

+

备注: ${employee.remark}

+
+ `; + } + + // 测试操作日志模型 + const operationLogDemo = Framework.dom.query('#operation-log-demo'); + if (operationLogDemo) { + // 创建操作日志实例 + const operationLog = Framework.model.OperationLog.create({ + id: 1, + uuid: '12345678901234567890123456789012', + tenant_id: 'tenant_001', + table_name: 'employee', + data_id: 1, + oper_type: 2, + oper_content: '修改员工姓名:张三→张三丰', + oper_by: 'EMP001', + ip: '192.168.1.100', + remark: '员工信息更新' + }); + + // 展示操作日志数据 + operationLogDemo.innerHTML = ` +
+

操作日志详情

+

日志ID: ${operationLog.id}

+

UUID: ${operationLog.uuid}

+

租户ID: ${operationLog.tenant_id}

+

操作表名: ${operationLog.table_name}

+

数据ID: ${operationLog.data_id}

+

操作类型: ${getOperTypeText(operationLog.oper_type)}

+

操作内容: ${operationLog.oper_content}

+

操作人: ${operationLog.oper_by}

+

操作时间: ${operationLog.oper_time}

+

操作IP: ${operationLog.ip}

+

备注: ${operationLog.remark}

+
+ `; + } + + // 测试岗位模型 + const positionDemo = Framework.dom.query('#position-demo'); + if (positionDemo) { + // 创建岗位实例 + const position = Framework.model.Position.create({ + id: 1, + uuid: '12345678901234567890123456789012', + company_id: 1, + dept_id: 1, + position_name: '销售部经理', + position_code: 'MANAGER', + position_type: 1, + sort: 1, + status: 1, + remark: '销售部负责人' + }); + + // 展示岗位数据 + positionDemo.innerHTML = ` +
+

岗位详情

+

岗位ID: ${position.id}

+

UUID: ${position.uuid}

+

公司ID: ${position.company_id}

+

部门ID: ${position.dept_id}

+

岗位名称: ${position.position_name}

+

岗位编码: ${position.position_code}

+

岗位类型: ${getPositionTypeText(position.position_type)}

+

排序: ${position.sort}

+

状态: ${position.status === 1 ? '正常' : '禁用'}

+

创建时间: ${position.create_time}

+

备注: ${position.remark}

+
+ `; + } +} + +/** + * 获取公司状态文本 + * @param {number} status - 状态码 + * @returns {string} - 状态文本 + */ +function getStatusText(status) { + const statusMap = { + 0: '禁用', + 1: '正常', + 2: '过期' + }; + return statusMap[status] || '未知'; +} + +/** + * 获取操作类型文本 + * @param {number} operType - 操作类型码 + * @returns {string} - 操作类型文本 + */ +function getOperTypeText(operType) { + const operTypeMap = { + 1: '新增', + 2: '修改', + 3: '删除', + 4: '禁用' + }; + return operTypeMap[operType] || '未知'; +} + +/** + * 获取岗位类型文本 + * @param {number} positionType - 岗位类型码 + * @returns {string} - 岗位类型文本 + */ +function getPositionTypeText(positionType) { + const positionTypeMap = { + 1: '管理岗', + 2: '技术岗', + 3: '职能岗' + }; + return positionTypeMap[positionType] || '未知'; +} \ No newline at end of file diff --git a/auth/login.html b/auth/login.html new file mode 100644 index 0000000..c38c780 --- /dev/null +++ b/auth/login.html @@ -0,0 +1,105 @@ + + + + + + 登录页面 + + + +
+

用户登录

+
+
+ + +
+
+ + +
+ +
+ 返回首页 + 没有账号?点击注册 +
+
+ + + + + + \ No newline at end of file diff --git a/auth/login.js b/auth/login.js new file mode 100644 index 0000000..d270d26 --- /dev/null +++ b/auth/login.js @@ -0,0 +1,55 @@ +/** + * 登录页面逻辑 + */ + +// 等待DOM加载完成 +document.addEventListener('DOMContentLoaded', function() { + // 获取登录表单 + const loginForm = document.getElementById('login-form'); + const errorMessage = document.getElementById('error-message'); + + // 监听表单提交事件 + loginForm.addEventListener('submit', async function(e) { + e.preventDefault(); + + // 获取用户输入 + const mobile = document.getElementById('mobile').value; + const pwd = document.getElementById('pwd').value; + + // 验证输入 + if (!mobile || !pwd) { + errorMessage.textContent = '请输入手机号和密码'; + return; + } + + // 构建请求数据 + const loginData = { + mobile: mobile, + password: pwd + }; + + try { + // 使用API服务发送登录请求 + const data = await API.auth.login(loginData); + + // 登录成功,创建员工实例 + const employee = Framework.model.Employee.create({ + mobile: data.mobile, + emp_name: data.empName, + emp_no: data.empNo, + dept_id: data.deptId, + position_id: data.positionId + }); + + // 存储用户信息到本地存储 + localStorage.setItem('currentUser', JSON.stringify(employee)); + + // 跳转到首页 + window.location.href = '../index.html'; + } catch (error) { + // 登录失败 + errorMessage.textContent = '登录失败,请检查手机号和密码'; + console.error('登录错误:', error); + } + }); +}); \ No newline at end of file diff --git a/auth/register.html b/auth/register.html new file mode 100644 index 0000000..563b34d --- /dev/null +++ b/auth/register.html @@ -0,0 +1,150 @@ + + + + + + 注册页面 + + + +
+

用户注册

+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+ +
+ +
+
+ + + + + + \ No newline at end of file diff --git a/auth/register.js b/auth/register.js new file mode 100644 index 0000000..a696cc7 --- /dev/null +++ b/auth/register.js @@ -0,0 +1,74 @@ +/** + * 注册页面逻辑 + */ + +// 等待DOM加载完成 +document.addEventListener('DOMContentLoaded', function() { + // 获取注册表单 + const registerForm = document.getElementById('register-form'); + const message = document.getElementById('message'); + + // 监听表单提交事件 + registerForm.addEventListener('submit', async function(e) { + e.preventDefault(); + + // 获取用户输入 + const company = document.getElementById('company').value; + const department = document.getElementById('department').value; + const position = document.getElementById('position').value; + const organization = document.getElementById('organization').value; + const emp_name = document.getElementById('emp_name').value; + const mobile = document.getElementById('mobile').value; + const pwd = document.getElementById('pwd').value; + + // 验证输入 + if (!company || !department || !position || !organization || !emp_name || !mobile || !pwd) { + message.textContent = '请填写所有必填字段'; + message.className = 'error-message'; + return; + } + + // 验证手机号格式 + if (!/^1[3-9][0-9]{9}$/.test(mobile)) { + message.textContent = '请输入正确的手机号'; + message.className = 'error-message'; + return; + } + + // 验证密码长度 + if (pwd.length < 6) { + message.textContent = '密码长度至少6位'; + message.className = 'error-message'; + return; + } + + // 构建请求数据 + const registerData = { + companyId: parseInt(company), + deptId: parseInt(department), + positionId: parseInt(position), + empName: emp_name, + mobile: mobile, + password: pwd + }; + + try { + // 使用API服务发送注册请求 + await API.auth.register(registerData); + + // 注册成功 + message.textContent = '注册成功!即将跳转到登录页面...'; + message.className = 'success-message'; + + // 3秒后跳转到登录页面 + setTimeout(function() { + window.location.href = 'login.html'; + }, 3000); + } catch (error) { + // 注册失败 + message.textContent = '注册失败,请稍后重试'; + message.className = 'error-message'; + console.error('注册错误:', error); + } + }); +}); \ No newline at end of file diff --git a/framework.js b/framework.js new file mode 100644 index 0000000..550d887 --- /dev/null +++ b/framework.js @@ -0,0 +1,293 @@ +/** + * 简单HTML5前端框架 + * 作者:前端架构师 + * 创建时间:2026-03-06 + * 版本:1.0.0 + * + * 框架功能: + * 1. DOM操作API + * 2. 组件系统 + * 3. 路由功能 + * 4. 状态管理 + */ + +// 框架核心对象 +const Framework = { + /** + * DOM操作API + */ + dom: { + /** + * 根据选择器获取元素 + * @param {string} selector - CSS选择器 + * @param {Element} context - 上下文元素,默认为document + * @returns {Element|null} - 匹配的元素 + */ + query: function(selector, context = document) { + return context.querySelector(selector); + }, + + /** + * 根据选择器获取多个元素 + * @param {string} selector - CSS选择器 + * @param {Element} context - 上下文元素,默认为document + * @returns {NodeList} - 匹配的元素列表 + */ + queryAll: function(selector, context = document) { + return context.querySelectorAll(selector); + }, + + /** + * 创建元素 + * @param {string} tagName - 标签名 + * @param {Object} options - 元素属性和事件 + * @returns {Element} - 创建的元素 + */ + create: function(tagName, options = {}) { + const element = document.createElement(tagName); + + // 设置属性 + if (options.attributes) { + Object.keys(options.attributes).forEach(attr => { + element.setAttribute(attr, options.attributes[attr]); + }); + } + + // 设置样式 + if (options.style) { + Object.assign(element.style, options.style); + } + + // 设置事件监听器 + if (options.events) { + Object.keys(options.events).forEach(event => { + element.addEventListener(event, options.events[event]); + }); + } + + // 设置文本内容 + if (options.text) { + element.textContent = options.text; + } + + return element; + }, + + /** + * 添加事件监听器 + * @param {Element} element - 目标元素 + * @param {string} event - 事件类型 + * @param {Function} callback - 回调函数 + */ + on: function(element, event, callback) { + element.addEventListener(event, callback); + }, + + /** + * 移除事件监听器 + * @param {Element} element - 目标元素 + * @param {string} event - 事件类型 + * @param {Function} callback - 回调函数 + */ + off: function(element, event, callback) { + element.removeEventListener(event, callback); + }, + + /** + * 触发事件 + * @param {Element} element - 目标元素 + * @param {string} event - 事件类型 + * @param {Object} detail - 事件详情 + */ + trigger: function(element, event, detail = {}) { + const customEvent = new CustomEvent(event, { detail }); + element.dispatchEvent(customEvent); + } + }, + + /** + * 组件系统 + */ + component: { + /** + * 注册组件 + * @param {string} name - 组件名称 + * @param {Function} constructor - 组件构造函数 + */ + register: function(name, constructor) { + if (!this.components) { + this.components = {}; + } + this.components[name] = constructor; + }, + + /** + * 创建组件实例 + * @param {string} name - 组件名称 + * @param {Object} props - 组件属性 + * @param {Element} container - 容器元素 + * @returns {Object} - 组件实例 + */ + create: function(name, props = {}, container = null) { + if (!this.components || !this.components[name]) { + throw new Error(`Component ${name} not registered`); + } + + const Component = this.components[name]; + const instance = new Component(props); + + if (container) { + instance.mount(container); + } + + return instance; + } + }, + + /** + * 路由功能 + */ + router: { + /** + * 路由配置 + */ + routes: {}, + + /** + * 初始化路由 + */ + init: function() { + // 监听哈希变化 + window.addEventListener('hashchange', this.handleHashChange.bind(this)); + // 初始加载 + this.handleHashChange(); + }, + + /** + * 注册路由 + * @param {string} path - 路由路径 + * @param {Function} handler - 路由处理函数 + */ + register: function(path, handler) { + this.routes[path] = handler; + }, + + /** + * 处理哈希变化 + */ + handleHashChange: function() { + const hash = window.location.hash || '#home'; + const path = hash.substring(1); + + if (this.routes[path]) { + this.routes[path](); + } + } + }, + + /** + * 状态管理 + */ + store: { + /** + * 状态数据 + */ + state: {}, + + /** + * 订阅者列表 + */ + subscribers: [], + + /** + * 获取状态 + * @param {string} key - 状态键名 + * @returns {*} - 状态值 + */ + get: function(key) { + return this.state[key]; + }, + + /** + * 设置状态 + * @param {string} key - 状态键名 + * @param {*} value - 状态值 + */ + set: function(key, value) { + this.state[key] = value; + this.notify(); + }, + + /** + * 订阅状态变化 + * @param {Function} callback - 回调函数 + * @returns {Function} - 取消订阅函数 + */ + subscribe: function(callback) { + this.subscribers.push(callback); + return () => { + this.subscribers = this.subscribers.filter(sub => sub !== callback); + }; + }, + + /** + * 通知订阅者 + */ + notify: function() { + this.subscribers.forEach(callback => callback(this.state)); + } + }, + + /** + * 工具方法 + */ + utils: { + /** + * 防抖函数 + * @param {Function} func - 要防抖的函数 + * @param {number} wait - 等待时间(毫秒) + * @returns {Function} - 防抖后的函数 + */ + debounce: function(func, wait) { + let timeout; + return function(...args) { + clearTimeout(timeout); + timeout = setTimeout(() => func.apply(this, args), wait); + }; + }, + + /** + * 节流函数 + * @param {Function} func - 要节流的函数 + * @param {number} limit - 时间限制(毫秒) + * @returns {Function} - 节流后的函数 + */ + throttle: function(func, limit) { + let inThrottle; + return function(...args) { + if (!inThrottle) { + func.apply(this, args); + inThrottle = true; + setTimeout(() => inThrottle = false, limit); + } + }; + } + }, + + /** + * 数据模型服务 + */ + model: { + AuditPermission: window.AuditPermission || {}, + Company: window.Company || {}, + Customer: window.Customer || {}, + CustomerContact: window.CustomerContact || {}, + Department: window.Department || {}, + Employee: window.Employee || {}, + OperationLog: window.OperationLog || {}, + Position: window.Position || {} + } +}; + +// 导出框架 +window.Framework = Framework; \ No newline at end of file diff --git a/index.html b/index.html new file mode 100644 index 0000000..0190eda --- /dev/null +++ b/index.html @@ -0,0 +1,199 @@ + + + + + + 简单HTML5前端框架 + + + +
+

简单HTML5前端框架

+
+ + 登录 + +
+
+ +
+
+

首页

+

欢迎使用简单HTML5前端框架!这是一个轻量级的前端框架,包含基本的DOM操作、组件系统、路由和状态管理功能。

+ 查看计数器示例 +
+ + + +
+ + + + + + + + + + + + + + \ No newline at end of file diff --git a/models/auditPermission.js b/models/auditPermission.js new file mode 100644 index 0000000..f5bcd4e --- /dev/null +++ b/models/auditPermission.js @@ -0,0 +1,64 @@ +/** + * 审核权限配置表模型 + */ + +const AuditPermission = { + /** + * 模型字段定义 + */ + fields: { + id: 'number', + uuid: 'string', + company_id: 'number', + position_id: 'number', + audit_type: 'string', + audit_level: 'number', + audit_scope: 'string', + max_audit_amount: 'number', + sort: 'number', + status: 'number', + effective_time: 'date', + invalid_time: 'date', + create_by: 'string', + create_time: 'date', + update_by: 'string', + update_time: 'date', + delete_by: 'number', + delete_time: 'date', + remark: 'string', + deleted: 'number' + }, + + /** + * 创建审核权限实例 + * @param {Object} data - 数据对象 + * @returns {Object} - 审核权限实例 + */ + create: function(data) { + return { + id: data.id || null, + uuid: data.uuid || '', + company_id: data.company_id || 0, + position_id: data.position_id || 0, + audit_type: data.audit_type || '', + audit_level: data.audit_level || 0, + audit_scope: data.audit_scope || '*', + max_audit_amount: data.max_audit_amount || null, + sort: data.sort || 0, + status: data.status || 1, + effective_time: data.effective_time || null, + invalid_time: data.invalid_time || null, + create_by: data.create_by || null, + create_time: data.create_time || new Date(), + update_by: data.update_by || null, + update_time: data.update_time || null, + delete_by: data.delete_by || null, + delete_time: data.delete_time || null, + remark: data.remark || '', + deleted: data.deleted || 0 + }; + } +}; + +// 导出为全局变量 +window.AuditPermission = AuditPermission; \ No newline at end of file diff --git a/models/company.js b/models/company.js new file mode 100644 index 0000000..40921fd --- /dev/null +++ b/models/company.js @@ -0,0 +1,66 @@ +/** + * 公司模型 + */ + +const Company = { + /** + * 模型字段定义 + */ + fields: { + id: 'number', + uuid: 'string', + company_name: 'string', + tenant_id: 'string', + parent_company_id: 'number', + short_name: 'string', + industry: 'string', + contact_mobile: 'string', + contact_email: 'string', + expire_time: 'date', + effective_time: 'date', + invalid_time: 'date', + status: 'number', + create_by: 'number', + create_time: 'date', + update_by: 'number', + update_time: 'date', + delete_by: 'number', + delete_time: 'date', + remark: 'string', + deleted: 'number' + }, + + /** + * 创建公司实例 + * @param {Object} data - 数据对象 + * @returns {Object} - 公司实例 + */ + create: function(data) { + return { + id: data.id || null, + uuid: data.uuid || '', + company_name: data.company_name || '', + tenant_id: data.tenant_id || '', + parent_company_id: data.parent_company_id || 0, + short_name: data.short_name || null, + industry: data.industry || null, + contact_mobile: data.contact_mobile || null, + contact_email: data.contact_email || null, + expire_time: data.expire_time || null, + effective_time: data.effective_time || null, + invalid_time: data.invalid_time || null, + status: data.status || 1, + create_by: data.create_by || 0, + create_time: data.create_time || new Date(), + update_by: data.update_by || null, + update_time: data.update_time || null, + delete_by: data.delete_by || null, + delete_time: data.delete_time || null, + remark: data.remark || '', + deleted: data.deleted || 0 + }; + } +}; + +// 导出为全局变量 +window.Company = Company; \ No newline at end of file diff --git a/models/customer.js b/models/customer.js new file mode 100644 index 0000000..40ad9b8 --- /dev/null +++ b/models/customer.js @@ -0,0 +1,56 @@ +/** + * 客户主表模型 + */ + +const Customer = { + /** + * 模型字段定义 + */ + fields: { + customer_id: 'number', + customer_name: 'string', + create_date: 'date', + last_order_date: 'date', + last_followup_date: 'date', + followup_status: 'string', + responsible_person: 'string', + department: 'string', + assistant: 'string', + region: 'string', + customer_type: 'string', + customer_level: 'string', + basic_requirements: 'string', + specifications: 'string', + created_at: 'date', + updated_at: 'date' + }, + + /** + * 创建客户实例 + * @param {Object} data - 数据对象 + * @returns {Object} - 客户实例 + */ + create: function(data) { + return { + customer_id: data.customer_id || null, + customer_name: data.customer_name || '', + create_date: data.create_date || null, + last_order_date: data.last_order_date || null, + last_followup_date: data.last_followup_date || null, + followup_status: data.followup_status || '', + responsible_person: data.responsible_person || null, + department: data.department || null, + assistant: data.assistant || null, + region: data.region || null, + customer_type: data.customer_type || null, + customer_level: data.customer_level || null, + basic_requirements: data.basic_requirements || '', + specifications: data.specifications || '', + created_at: data.created_at || new Date(), + updated_at: data.updated_at || new Date() + }; + } +}; + +// 导出为全局变量 +window.Customer = Customer; \ No newline at end of file diff --git a/models/customerContact.js b/models/customerContact.js new file mode 100644 index 0000000..8c99972 --- /dev/null +++ b/models/customerContact.js @@ -0,0 +1,48 @@ +/** + * 客户联系信息子表模型 + */ + +const CustomerContact = { + /** + * 模型字段定义 + */ + fields: { + contact_id: 'number', + customer_id: 'number', + wechat_id: 'string', + contact_name: 'string', + phone: 'string', + account: 'string', + account_number: 'string', + bank: 'string', + address: 'string', + company_name: 'string', + created_at: 'date', + updated_at: 'date' + }, + + /** + * 创建客户联系信息实例 + * @param {Object} data - 数据对象 + * @returns {Object} - 客户联系信息实例 + */ + create: function(data) { + return { + contact_id: data.contact_id || null, + customer_id: data.customer_id || 0, + wechat_id: data.wechat_id || null, + contact_name: data.contact_name || null, + phone: data.phone || null, + account: data.account || null, + account_number: data.account_number || null, + bank: data.bank || null, + address: data.address || '', + company_name: data.company_name || null, + created_at: data.created_at || new Date(), + updated_at: data.updated_at || new Date() + }; + } +}; + +// 导出为全局变量 +window.CustomerContact = CustomerContact; \ No newline at end of file diff --git a/models/department.js b/models/department.js new file mode 100644 index 0000000..9323dec --- /dev/null +++ b/models/department.js @@ -0,0 +1,64 @@ +/** + * 部门表模型 + */ + +const Department = { + /** + * 模型字段定义 + */ + fields: { + id: 'number', + uuid: 'string', + company_id: 'number', + dept_name: 'string', + parent_id: 'number', + dept_level: 'number', + dept_code: 'string', + leader_id: 'number', + sort: 'number', + status: 'number', + effective_time: 'date', + invalid_time: 'date', + create_by: 'number', + create_time: 'date', + update_by: 'number', + update_time: 'date', + delete_by: 'number', + delete_time: 'date', + remark: 'string', + deleted: 'number' + }, + + /** + * 创建部门实例 + * @param {Object} data - 数据对象 + * @returns {Object} - 部门实例 + */ + create: function(data) { + return { + id: data.id || null, + uuid: data.uuid || '', + company_id: data.company_id || 0, + dept_name: data.dept_name || '', + parent_id: data.parent_id || 0, + dept_level: data.dept_level || 1, + dept_code: data.dept_code || null, + leader_id: data.leader_id || null, + sort: data.sort || 0, + status: data.status || 1, + effective_time: data.effective_time || null, + invalid_time: data.invalid_time || null, + create_by: data.create_by || null, + create_time: data.create_time || new Date(), + update_by: data.update_by || null, + update_time: data.update_time || new Date(), + delete_by: data.delete_by || null, + delete_time: data.delete_time || null, + remark: data.remark || '', + deleted: data.deleted || 0 + }; + } +}; + +// 导出为全局变量 +window.Department = Department; \ No newline at end of file diff --git a/models/employee.js b/models/employee.js new file mode 100644 index 0000000..5d149fb --- /dev/null +++ b/models/employee.js @@ -0,0 +1,82 @@ +/** + * 公司员工表模型 + */ + +const Employee = { + /** + * 模型字段定义 + */ + fields: { + id: 'number', + uuid: 'string', + company_id: 'number', + dept_id: 'number', + position_id: 'number', + emp_name: 'string', + mobile: 'string', + pwd: 'string', + emp_no: 'string', + email: 'string', + id_card: 'string', + id_card_encrypted: 'string', + entry_time: 'date', + leave_time: 'date', + is_admin: 'number', + is_leader: 'number', + status: 'number', + effective_time: 'date', + invalid_time: 'date', + last_login_time: 'date', + create_by: 'number', + create_time: 'date', + update_by: 'number', + update_time: 'date', + delete_by: 'number', + delete_time: 'date', + remark: 'string', + deleted: 'number', + mobile_encrypted: 'string' + }, + + /** + * 创建员工实例 + * @param {Object} data - 数据对象 + * @returns {Object} - 员工实例 + */ + create: function(data) { + return { + id: data.id || null, + uuid: data.uuid || '', + company_id: data.company_id || 0, + dept_id: data.dept_id || 0, + position_id: data.position_id || 0, + emp_name: data.emp_name || '', + mobile: data.mobile || null, + pwd: data.pwd || null, + emp_no: data.emp_no || '', + email: data.email || null, + id_card: data.id_card || null, + id_card_encrypted: data.id_card_encrypted || null, + entry_time: data.entry_time || null, + leave_time: data.leave_time || null, + is_admin: data.is_admin || 0, + is_leader: data.is_leader || 0, + status: data.status || 1, + effective_time: data.effective_time || null, + invalid_time: data.invalid_time || null, + last_login_time: data.last_login_time || null, + create_by: data.create_by || null, + create_time: data.create_time || new Date(), + update_by: data.update_by || null, + update_time: data.update_time || new Date(), + delete_by: data.delete_by || null, + delete_time: data.delete_time || null, + remark: data.remark || '', + deleted: data.deleted || 0, + mobile_encrypted: data.mobile_encrypted || null + }; + } +}; + +// 导出为全局变量 +window.Employee = Employee; \ No newline at end of file diff --git a/models/index.js b/models/index.js new file mode 100644 index 0000000..0241ddb --- /dev/null +++ b/models/index.js @@ -0,0 +1,28 @@ +/** + * 模型管理索引文件 + * 集中导出所有数据模型 + */ + +// 导入各个模型 +import AuditPermission from './auditPermission.js'; +import Company from './company.js'; +import Customer from './customer.js'; +import CustomerContact from './customerContact.js'; +import Department from './department.js'; +import Employee from './employee.js'; +import OperationLog from './operationLog.js'; +import Position from './position.js'; + +// 导出所有模型 +const models = { + AuditPermission, + Company, + Customer, + CustomerContact, + Department, + Employee, + OperationLog, + Position +}; + +export default models; \ No newline at end of file diff --git a/models/operationLog.js b/models/operationLog.js new file mode 100644 index 0000000..2fa82fc --- /dev/null +++ b/models/operationLog.js @@ -0,0 +1,46 @@ +/** + * 系统操作日志表模型 + */ + +const OperationLog = { + /** + * 模型字段定义 + */ + fields: { + id: 'number', + uuid: 'string', + tenant_id: 'string', + table_name: 'string', + data_id: 'number', + oper_type: 'number', + oper_content: 'string', + oper_by: 'string', + oper_time: 'date', + remark: 'string', + ip: 'string' + }, + + /** + * 创建操作日志实例 + * @param {Object} data - 数据对象 + * @returns {Object} - 操作日志实例 + */ + create: function(data) { + return { + id: data.id || null, + uuid: data.uuid || '', + tenant_id: data.tenant_id || '', + table_name: data.table_name || '', + data_id: data.data_id || 0, + oper_type: data.oper_type || 0, + oper_content: data.oper_content || '', + oper_by: data.oper_by || '', + oper_time: data.oper_time || new Date(), + remark: data.remark || '', + ip: data.ip || null + }; + } +}; + +// 导出为全局变量 +window.OperationLog = OperationLog; \ No newline at end of file diff --git a/models/position.js b/models/position.js new file mode 100644 index 0000000..4bbb6b0 --- /dev/null +++ b/models/position.js @@ -0,0 +1,62 @@ +/** + * 公司岗位表模型 + */ + +const Position = { + /** + * 模型字段定义 + */ + fields: { + id: 'number', + uuid: 'string', + company_id: 'number', + dept_id: 'number', + position_name: 'string', + position_code: 'string', + position_type: 'number', + sort: 'number', + status: 'number', + effective_time: 'date', + invalid_time: 'date', + create_by: 'number', + create_time: 'date', + update_by: 'number', + update_time: 'date', + delete_by: 'number', + delete_time: 'date', + remark: 'string', + deleted: 'number' + }, + + /** + * 创建岗位实例 + * @param {Object} data - 数据对象 + * @returns {Object} - 岗位实例 + */ + create: function(data) { + return { + id: data.id || null, + uuid: data.uuid || '', + company_id: data.company_id || 0, + dept_id: data.dept_id || 0, + position_name: data.position_name || '', + position_code: data.position_code || null, + position_type: data.position_type || 1, + sort: data.sort || 0, + status: data.status || 1, + effective_time: data.effective_time || null, + invalid_time: data.invalid_time || null, + create_by: data.create_by || null, + create_time: data.create_time || new Date(), + update_by: data.update_by || null, + update_time: data.update_time || new Date(), + delete_by: data.delete_by || null, + delete_time: data.delete_time || null, + remark: data.remark || '', + deleted: data.deleted || 0 + }; + } +}; + +// 导出为全局变量 +window.Position = Position; \ No newline at end of file