瞪眼法测试通过
This commit is contained in:
@@ -2,6 +2,24 @@
|
||||
const { pool } = require('../db')
|
||||
const { getDataScope } = require('../middleware/permissions')
|
||||
|
||||
// 格式化日期为 YYYY-MM-DD
|
||||
function formatDate(dateStr) {
|
||||
if (!dateStr) return null
|
||||
if (typeof dateStr === 'string' && /^\d{4}-\d{2}-\d{2}$/.test(dateStr)) {
|
||||
return dateStr
|
||||
}
|
||||
try {
|
||||
const date = new Date(dateStr)
|
||||
if (isNaN(date.getTime())) return null
|
||||
const year = date.getFullYear()
|
||||
const month = String(date.getMonth() + 1).padStart(2, '0')
|
||||
const day = String(date.getDate()).padStart(2, '0')
|
||||
return `${year}-${month}-${day}`
|
||||
} catch {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
function pagination(query) {
|
||||
const page = Math.max(Number(query.page) || 1, 1)
|
||||
const pageSize = Math.min(Math.max(Number(query.pageSize) || 10, 1), 100)
|
||||
@@ -23,7 +41,7 @@ const LIST_SELECT = `
|
||||
async function list(req, res) {
|
||||
try {
|
||||
const { page, pageSize, offset } = pagination(req.query)
|
||||
const { handle_status, customer_name } = req.query
|
||||
const { handle_status, customer_name, id, customer_id, feedback } = req.query
|
||||
|
||||
let where = 'WHERE 1=1'
|
||||
const params = []
|
||||
@@ -35,11 +53,23 @@ async function list(req, res) {
|
||||
}
|
||||
if (scope.where) {
|
||||
// list 查询有 JOIN,需要表别名前缀避免列名歧义
|
||||
const scopeCol = scope.tableAlias ? scope.where.replace('responsible_user_id', `${scope.tableAlias}.responsible_user_id`) : scope.where
|
||||
const scopeCol = scope.tableAlias ? scope.where.replace(/\bresponsible_user_id\b/g, `${scope.tableAlias}.responsible_user_id`) : scope.where
|
||||
where += ' AND ' + scopeCol
|
||||
params.push(...scope.values)
|
||||
}
|
||||
|
||||
if (id) {
|
||||
where += ' AND a.id = ?'
|
||||
params.push(id)
|
||||
}
|
||||
if (customer_id) {
|
||||
where += ' AND a.customer_id = ?'
|
||||
params.push(customer_id)
|
||||
}
|
||||
if (feedback) {
|
||||
where += ' AND a.feedback LIKE ?'
|
||||
params.push(`%${feedback}%`)
|
||||
}
|
||||
if (handle_status) {
|
||||
where += ' AND a.handle_status = ?'
|
||||
params.push(handle_status)
|
||||
@@ -145,7 +175,7 @@ async function create(req, res) {
|
||||
employee_id || null,
|
||||
handle_method || null,
|
||||
handle_status || '待处理',
|
||||
service_date || null,
|
||||
formatDate(service_date),
|
||||
remark || null,
|
||||
ownerId]
|
||||
)
|
||||
@@ -201,7 +231,12 @@ async function update(req, res) {
|
||||
for (const f of fields) {
|
||||
if (req.body[f] !== undefined) {
|
||||
sets.push(`${f} = ?`)
|
||||
params.push(req.body[f])
|
||||
// 日期字段需要格式化
|
||||
if (f === 'service_date') {
|
||||
params.push(formatDate(req.body[f]))
|
||||
} else {
|
||||
params.push(req.body[f])
|
||||
}
|
||||
}
|
||||
}
|
||||
if (sets.length === 0) {
|
||||
|
||||
@@ -2,6 +2,24 @@
|
||||
const { pool } = require('../db')
|
||||
const { getDataScope } = require('../middleware/permissions')
|
||||
|
||||
// 格式化日期为 YYYY-MM-DD
|
||||
function formatDate(dateStr) {
|
||||
if (!dateStr) return null
|
||||
if (typeof dateStr === 'string' && /^\d{4}-\d{2}-\d{2}$/.test(dateStr)) {
|
||||
return dateStr
|
||||
}
|
||||
try {
|
||||
const date = new Date(dateStr)
|
||||
if (isNaN(date.getTime())) return null
|
||||
const year = date.getFullYear()
|
||||
const month = String(date.getMonth() + 1).padStart(2, '0')
|
||||
const day = String(date.getDate()).padStart(2, '0')
|
||||
return `${year}-${month}-${day}`
|
||||
} catch {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
function pagination(query) {
|
||||
const page = Math.max(Number(query.page) || 1, 1)
|
||||
const pageSize = Math.min(Math.max(Number(query.pageSize) || 10, 1), 100)
|
||||
@@ -9,14 +27,16 @@ function pagination(query) {
|
||||
return { page, pageSize, offset }
|
||||
}
|
||||
|
||||
// 列表查询时 JOIN 客户名和员工名
|
||||
// 列表查询时 JOIN 客户名、供应商名和员工名
|
||||
const LIST_SELECT = `
|
||||
SELECT
|
||||
c.*,
|
||||
cu.name AS customer_name,
|
||||
s.name AS supplier_name,
|
||||
e.name AS employee_name
|
||||
FROM contracts c
|
||||
LEFT JOIN customers cu ON c.customer_id = cu.id
|
||||
LEFT JOIN suppliers s ON c.supplier_id = s.id
|
||||
LEFT JOIN employees e ON c.employee_id = e.id
|
||||
`
|
||||
|
||||
@@ -27,25 +47,35 @@ const DETAIL_SELECT = LIST_SELECT
|
||||
async function list(req, res) {
|
||||
try {
|
||||
const { page, pageSize, offset } = pagination(req.query)
|
||||
const { status, customer_name, contract_no, employee_name } = req.query
|
||||
const { status, customer_name, contract_no, contract_name, employee_name, id, effective_date_start, effective_date_end } = req.query
|
||||
|
||||
let where = 'WHERE 1=1'
|
||||
const params = []
|
||||
|
||||
// 数据范围过滤
|
||||
// 数据范围过滤(列表查询使用表别名 c,需要加前缀)
|
||||
const scope = getDataScope(req.user, 'contracts')
|
||||
if (scope.deny) {
|
||||
return res.status(403).json({ code: 403, message: '无权访问此资源' })
|
||||
}
|
||||
if (scope.where) {
|
||||
where += ' AND ' + scope.where
|
||||
// 给 scope.where 中的字段加上表别名 c.
|
||||
const scopedWhere = scope.where.replace(/\b(responsible_user_id|type)\b/g, 'c.$1')
|
||||
where += ' AND ' + scopedWhere
|
||||
params.push(...scope.values)
|
||||
}
|
||||
|
||||
if (id) {
|
||||
where += ' AND c.id = ?'
|
||||
params.push(id)
|
||||
}
|
||||
if (status) {
|
||||
where += ' AND c.status = ?'
|
||||
params.push(status)
|
||||
}
|
||||
if (contract_name) {
|
||||
where += ' AND c.contract_name LIKE ?'
|
||||
params.push(`%${contract_name}%`)
|
||||
}
|
||||
if (customer_name) {
|
||||
where += ' AND cu.name LIKE ?'
|
||||
params.push(`%${customer_name}%`)
|
||||
@@ -58,10 +88,19 @@ async function list(req, res) {
|
||||
where += ' AND e.name LIKE ?'
|
||||
params.push(`%${employee_name}%`)
|
||||
}
|
||||
if (effective_date_start) {
|
||||
where += ' AND c.effective_date >= ?'
|
||||
params.push(effective_date_start)
|
||||
}
|
||||
if (effective_date_end) {
|
||||
where += ' AND c.effective_date <= ?'
|
||||
params.push(effective_date_end)
|
||||
}
|
||||
|
||||
const [[{ total }]] = await pool.query(
|
||||
`SELECT COUNT(*) AS total FROM contracts c
|
||||
LEFT JOIN customers cu ON c.customer_id = cu.id
|
||||
LEFT JOIN suppliers s ON c.supplier_id = s.id
|
||||
LEFT JOIN employees e ON c.employee_id = e.id
|
||||
${where}`,
|
||||
params
|
||||
@@ -100,7 +139,9 @@ async function detail(req, res) {
|
||||
return res.status(403).json({ code: 403, message: '无权访问此资源' })
|
||||
}
|
||||
if (scope.where) {
|
||||
sql += ' AND ' + scope.where
|
||||
// detail 查询使用表别名 c,需要给 scope.where 加上前缀
|
||||
const scopedWhere = scope.where.replace(/\b(responsible_user_id|type)\b/g, 'c.$1')
|
||||
sql += ' AND ' + scopedWhere
|
||||
params.push(...scope.values)
|
||||
}
|
||||
|
||||
@@ -118,22 +159,43 @@ async function detail(req, res) {
|
||||
// POST /api/contracts —— 新增
|
||||
async function create(req, res) {
|
||||
const {
|
||||
customer_id, contract_name, contract_no, contract_content,
|
||||
customer_id, supplier_id, contract_name, contract_no, contract_content,
|
||||
amount, effective_date, expiry_date, employee_id, status, remark,
|
||||
} = req.body || {}
|
||||
|
||||
if (!customer_id) {
|
||||
return res.status(400).json({ code: 400, message: '客户ID必填' })
|
||||
// 根据角色限制合同类型
|
||||
const contractType = req.body.type || (req.user.roleName === 'procurement_manager' ? 'supply' : 'franchise')
|
||||
if (req.user.roleName === 'procurement_manager' && contractType !== 'supply') {
|
||||
return res.status(403).json({ code: 403, message: '采购经理只能创建采购合同' })
|
||||
}
|
||||
if (req.user.roleName === 'franchise_manager' && contractType !== 'franchise') {
|
||||
return res.status(403).json({ code: 403, message: '招商经理只能创建加盟合同' })
|
||||
}
|
||||
|
||||
if (contractType === 'supply' && !supplier_id) {
|
||||
return res.status(400).json({ code: 400, message: '采购合同必须选择供应商' })
|
||||
}
|
||||
if (contractType !== 'supply' && !customer_id) {
|
||||
return res.status(400).json({ code: 400, message: '加盟合同必须选择客户' })
|
||||
}
|
||||
if (!contract_name) {
|
||||
return res.status(400).json({ code: 400, message: '合同名称必填' })
|
||||
}
|
||||
|
||||
try {
|
||||
// 校验客户是否存在
|
||||
const [cust] = await pool.query('SELECT id FROM customers WHERE id = ?', [customer_id])
|
||||
if (cust.length === 0) {
|
||||
return res.status(400).json({ code: 400, message: '关联客户不存在' })
|
||||
// 校验客户是否存在(非采购合同必填)
|
||||
if (customer_id) {
|
||||
const [cust] = await pool.query('SELECT id FROM customers WHERE id = ?', [customer_id])
|
||||
if (cust.length === 0) {
|
||||
return res.status(400).json({ code: 400, message: '关联客户不存在' })
|
||||
}
|
||||
}
|
||||
// 校验供应商是否存在(采购合同必填)
|
||||
if (supplier_id) {
|
||||
const [sup] = await pool.query('SELECT id FROM suppliers WHERE id = ?', [supplier_id])
|
||||
if (sup.length === 0) {
|
||||
return res.status(400).json({ code: 400, message: '关联供应商不存在' })
|
||||
}
|
||||
}
|
||||
// 校验业务员(如果填了)
|
||||
if (employee_id) {
|
||||
@@ -145,18 +207,18 @@ async function create(req, res) {
|
||||
|
||||
const [result] = await pool.query(
|
||||
`INSERT INTO contracts
|
||||
(customer_id, contract_name, contract_no, contract_content, amount, effective_date, expiry_date, employee_id, status, remark, type, responsible_user_id)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||
[customer_id, contract_name,
|
||||
(customer_id, supplier_id, contract_name, contract_no, contract_content, amount, effective_date, expiry_date, employee_id, status, remark, type, responsible_user_id)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||
[customer_id || null, supplier_id || null, contract_name,
|
||||
contract_no || null,
|
||||
contract_content || null,
|
||||
amount !== undefined ? amount : null,
|
||||
effective_date || null,
|
||||
expiry_date || null,
|
||||
formatDate(effective_date),
|
||||
formatDate(expiry_date),
|
||||
employee_id || null,
|
||||
status || '生效',
|
||||
status || '生效中',
|
||||
remark || null,
|
||||
req.body.type || (req.user.roleName === 'procurement_manager' ? 'supply' : 'franchise'),
|
||||
contractType,
|
||||
req.body.responsible_user_id || req.user.id]
|
||||
)
|
||||
|
||||
@@ -172,12 +234,12 @@ async function create(req, res) {
|
||||
async function update(req, res) {
|
||||
const { id } = req.params
|
||||
const fields = [
|
||||
'customer_id', 'contract_name', 'contract_no', 'contract_content',
|
||||
'customer_id', 'supplier_id', 'contract_name', 'contract_no', 'contract_content',
|
||||
'amount', 'effective_date', 'expiry_date', 'employee_id', 'status', 'remark', 'type', 'responsible_user_id',
|
||||
]
|
||||
|
||||
try {
|
||||
// 确认记录存在且在数据范围内
|
||||
// 确认记录存在且在数据范围内(detail/update/delete 不用表别名)
|
||||
let checkSql = 'SELECT id FROM contracts WHERE id = ?'
|
||||
const checkParams = [id]
|
||||
const scope = getDataScope(req.user, 'contracts')
|
||||
@@ -206,13 +268,24 @@ async function update(req, res) {
|
||||
return res.status(400).json({ code: 400, message: '关联业务员不存在' })
|
||||
}
|
||||
}
|
||||
if (req.body.supplier_id) {
|
||||
const [sup] = await pool.query('SELECT id FROM suppliers WHERE id = ?', [req.body.supplier_id])
|
||||
if (sup.length === 0) {
|
||||
return res.status(400).json({ code: 400, message: '关联供应商不存在' })
|
||||
}
|
||||
}
|
||||
|
||||
const sets = []
|
||||
const params = []
|
||||
for (const f of fields) {
|
||||
if (req.body[f] !== undefined) {
|
||||
sets.push(`${f} = ?`)
|
||||
params.push(req.body[f])
|
||||
// 日期字段需要格式化
|
||||
if (['effective_date', 'expiry_date'].includes(f)) {
|
||||
params.push(formatDate(req.body[f]))
|
||||
} else {
|
||||
params.push(req.body[f])
|
||||
}
|
||||
}
|
||||
}
|
||||
if (sets.length === 0) {
|
||||
|
||||
@@ -14,7 +14,7 @@ function pagination(query) {
|
||||
async function list(req, res) {
|
||||
try {
|
||||
const { page, pageSize, offset } = pagination(req.query)
|
||||
const { name, phone, province, city } = req.query
|
||||
const { name, phone, province, city, id } = req.query
|
||||
|
||||
let where = 'WHERE 1=1'
|
||||
const params = []
|
||||
@@ -29,32 +29,40 @@ async function list(req, res) {
|
||||
params.push(...scope.values)
|
||||
}
|
||||
|
||||
if (id) {
|
||||
where += ' AND c.id = ?'
|
||||
params.push(id)
|
||||
}
|
||||
if (name) {
|
||||
where += ' AND name LIKE ?'
|
||||
where += ' AND c.name LIKE ?'
|
||||
params.push(`%${name}%`)
|
||||
}
|
||||
if (phone) {
|
||||
where += ' AND phone LIKE ?'
|
||||
where += ' AND c.phone LIKE ?'
|
||||
params.push(`%${phone}%`)
|
||||
}
|
||||
if (province) {
|
||||
where += ' AND province = ?'
|
||||
where += ' AND c.province = ?'
|
||||
params.push(province)
|
||||
}
|
||||
if (city) {
|
||||
where += ' AND city = ?'
|
||||
where += ' AND c.city = ?'
|
||||
params.push(city)
|
||||
}
|
||||
|
||||
// 查总数
|
||||
const [[{ total }]] = await pool.query(
|
||||
`SELECT COUNT(*) AS total FROM customers ${where}`,
|
||||
`SELECT COUNT(*) AS total FROM customers c ${where}`,
|
||||
params
|
||||
)
|
||||
|
||||
// 查分页数据
|
||||
// 查分页数据(JOIN users+employees 获取负责人姓名)
|
||||
const [rows] = await pool.query(
|
||||
`SELECT * FROM customers ${where} ORDER BY id DESC LIMIT ? OFFSET ?`,
|
||||
`SELECT c.*, e.name AS responsible_user_name
|
||||
FROM customers c
|
||||
LEFT JOIN users u ON c.responsible_user_id = u.id
|
||||
LEFT JOIN employees e ON u.employee_id = e.id
|
||||
${where} ORDER BY c.id DESC LIMIT ? OFFSET ?`,
|
||||
[...params, pageSize, offset]
|
||||
)
|
||||
|
||||
@@ -201,6 +209,9 @@ async function remove(req, res) {
|
||||
res.json({ code: 0, message: 'ok' })
|
||||
} catch (e) {
|
||||
console.error('[customers delete] error:', e)
|
||||
if (e.code === 'ER_ROW_IS_REFERENCED_2') {
|
||||
return res.status(400).json({ code: 400, message: '该客户被合同或售后记录引用,无法删除' })
|
||||
}
|
||||
res.status(500).json({ code: 500, message: e.message })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,24 @@
|
||||
const { pool } = require('../db')
|
||||
const { getDataScope } = require('../middleware/permissions')
|
||||
|
||||
// 格式化日期为 YYYY-MM-DD
|
||||
function formatDate(dateStr) {
|
||||
if (!dateStr) return null
|
||||
if (typeof dateStr === 'string' && /^\d{4}-\d{2}-\d{2}$/.test(dateStr)) {
|
||||
return dateStr // 已经是正确格式
|
||||
}
|
||||
try {
|
||||
const date = new Date(dateStr)
|
||||
if (isNaN(date.getTime())) return null
|
||||
const year = date.getFullYear()
|
||||
const month = String(date.getMonth() + 1).padStart(2, '0')
|
||||
const day = String(date.getDate()).padStart(2, '0')
|
||||
return `${year}-${month}-${day}`
|
||||
} catch {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
function pagination(query) {
|
||||
const page = Math.max(Number(query.page) || 1, 1)
|
||||
const pageSize = Math.min(Math.max(Number(query.pageSize) || 10, 1), 100)
|
||||
@@ -13,7 +31,7 @@ function pagination(query) {
|
||||
async function list(req, res) {
|
||||
try {
|
||||
const { page, pageSize, offset } = pagination(req.query)
|
||||
const { name, department, status } = req.query
|
||||
const { id, name, status, department } = req.query
|
||||
|
||||
let where = 'WHERE 1=1'
|
||||
const params = []
|
||||
@@ -28,18 +46,22 @@ async function list(req, res) {
|
||||
params.push(...scope.values)
|
||||
}
|
||||
|
||||
if (id) {
|
||||
where += ' AND id = ?'
|
||||
params.push(Number(id))
|
||||
}
|
||||
if (name) {
|
||||
where += ' AND name LIKE ?'
|
||||
params.push(`%${name}%`)
|
||||
}
|
||||
if (department) {
|
||||
where += ' AND department LIKE ?'
|
||||
params.push(`%${department}%`)
|
||||
}
|
||||
if (status !== undefined && status !== '') {
|
||||
where += ' AND status = ?'
|
||||
params.push(Number(status))
|
||||
}
|
||||
if (department) {
|
||||
where += ' AND department LIKE ?'
|
||||
params.push(`%${department}%`)
|
||||
}
|
||||
|
||||
const [[{ total }]] = await pool.query(
|
||||
`SELECT COUNT(*) AS total FROM employees ${where}`,
|
||||
@@ -114,7 +136,7 @@ async function create(req, res) {
|
||||
age !== undefined ? age : null,
|
||||
education || null,
|
||||
department || null,
|
||||
entry_date || null,
|
||||
formatDate(entry_date),
|
||||
position || null,
|
||||
salary !== undefined ? salary : null,
|
||||
phone || null,
|
||||
@@ -160,7 +182,12 @@ async function update(req, res) {
|
||||
for (const f of fields) {
|
||||
if (req.body[f] !== undefined) {
|
||||
sets.push(`${f} = ?`)
|
||||
params.push(req.body[f])
|
||||
// 日期字段需要格式化
|
||||
if (f === 'entry_date') {
|
||||
params.push(formatDate(req.body[f]))
|
||||
} else {
|
||||
params.push(req.body[f])
|
||||
}
|
||||
}
|
||||
}
|
||||
if (sets.length === 0) {
|
||||
@@ -170,6 +197,11 @@ async function update(req, res) {
|
||||
params.push(id)
|
||||
await pool.query(`UPDATE employees SET ${sets.join(', ')} WHERE id = ?`, params)
|
||||
|
||||
// 同步 department 到关联的 users 表
|
||||
if (req.body.department !== undefined) {
|
||||
await pool.query('UPDATE users SET department = ? WHERE employee_id = ?', [req.body.department, id])
|
||||
}
|
||||
|
||||
const [rows] = await pool.query('SELECT * FROM employees WHERE id = ?', [id])
|
||||
res.json({ code: 0, message: 'ok', data: rows[0] })
|
||||
} catch (e) {
|
||||
@@ -196,10 +228,20 @@ async function remove(req, res) {
|
||||
if (existing.length === 0) {
|
||||
return res.status(404).json({ code: 404, message: '员工不存在或无权操作' })
|
||||
}
|
||||
// 禁止删除自己关联的员工
|
||||
const [selfCheck] = await pool.query('SELECT id FROM users WHERE employee_id = ? AND id = ?', [id, req.user.id])
|
||||
if (selfCheck.length > 0) {
|
||||
return res.status(400).json({ code: 400, message: '不能删除自己的员工账号' })
|
||||
}
|
||||
// 同步删除关联的用户账号
|
||||
await pool.query('DELETE FROM users WHERE employee_id = ?', [id])
|
||||
await pool.query('DELETE FROM employees WHERE id = ?', [id])
|
||||
res.json({ code: 0, message: 'ok' })
|
||||
} catch (e) {
|
||||
console.error('[employees delete] error:', e)
|
||||
if (e.code === 'ER_ROW_IS_REFERENCED_2') {
|
||||
return res.status(400).json({ code: 400, message: '该员工被合同或售后记录引用,无法删除' })
|
||||
}
|
||||
res.status(500).json({ code: 500, message: e.message })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,11 +12,15 @@ function pagination(query) {
|
||||
async function list(req, res) {
|
||||
try {
|
||||
const { page, pageSize, offset } = pagination(req.query)
|
||||
const { name, type, supplier } = req.query
|
||||
const { name, type, supplier, id } = req.query
|
||||
|
||||
let where = 'WHERE 1=1'
|
||||
const params = []
|
||||
|
||||
if (id) {
|
||||
where += ' AND id = ?'
|
||||
params.push(id)
|
||||
}
|
||||
if (name) {
|
||||
where += ' AND name LIKE ?'
|
||||
params.push(`%${name}%`)
|
||||
@@ -150,6 +154,9 @@ async function remove(req, res) {
|
||||
res.json({ code: 0, message: 'ok' })
|
||||
} catch (e) {
|
||||
console.error('[products delete] error:', e)
|
||||
if (e.code === 'ER_ROW_IS_REFERENCED_2') {
|
||||
return res.status(400).json({ code: 400, message: '该产品被引用,无法删除' })
|
||||
}
|
||||
res.status(500).json({ code: 500, message: e.message })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,11 +12,15 @@ function pagination(query) {
|
||||
async function list(req, res) {
|
||||
try {
|
||||
const { page, pageSize, offset } = pagination(req.query)
|
||||
const { name, type, status } = req.query
|
||||
const { id, name, type, status } = req.query
|
||||
|
||||
let where = 'WHERE 1=1'
|
||||
const params = []
|
||||
|
||||
if (id) {
|
||||
where += ' AND id = ?'
|
||||
params.push(Number(id))
|
||||
}
|
||||
if (name) {
|
||||
where += ' AND name LIKE ?'
|
||||
params.push(`%${name}%`)
|
||||
@@ -140,6 +144,9 @@ async function remove(req, res) {
|
||||
res.json({ code: 0, message: 'ok' })
|
||||
} catch (e) {
|
||||
console.error('[suppliers delete] error:', e)
|
||||
if (e.code === 'ER_ROW_IS_REFERENCED_2') {
|
||||
return res.status(400).json({ code: 400, message: '该供应商被合同引用,无法删除' })
|
||||
}
|
||||
res.status(500).json({ code: 500, message: e.message })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,6 +118,21 @@ async function info(req, res) {
|
||||
}
|
||||
}
|
||||
|
||||
// GET /api/user/list —— 简易用户列表(用于下拉选择负责人,仅需登录)
|
||||
async function simpleList(req, res) {
|
||||
try {
|
||||
const [rows] = await pool.query(
|
||||
`SELECT u.id, u.username, e.name AS real_name
|
||||
FROM users u LEFT JOIN employees e ON u.employee_id = e.id
|
||||
WHERE u.is_active = 1 ORDER BY u.id`
|
||||
)
|
||||
res.json({ code: 0, message: 'ok', data: rows })
|
||||
} catch (e) {
|
||||
console.error('[user simpleList] error:', e)
|
||||
res.status(500).json({ code: 500, message: e.message })
|
||||
}
|
||||
}
|
||||
|
||||
// POST /api/user/logout —— 登出(需要 token,仅做应答)
|
||||
async function logout(req, res) {
|
||||
res.json({ code: 0, message: 'ok' })
|
||||
@@ -162,7 +177,7 @@ async function changePassword(req, res) {
|
||||
async function list(req, res) {
|
||||
try {
|
||||
const { page, pageSize, offset } = pagination(req.query)
|
||||
const { username, role_id, is_active } = req.query
|
||||
const { username, real_name, id, role_id, is_active } = req.query
|
||||
|
||||
let where = 'WHERE 1=1'
|
||||
const params = []
|
||||
@@ -171,6 +186,14 @@ async function list(req, res) {
|
||||
where += ' AND u.username LIKE ?'
|
||||
params.push(`%${username}%`)
|
||||
}
|
||||
if (real_name) {
|
||||
where += ' AND e.name LIKE ?'
|
||||
params.push(`%${real_name}%`)
|
||||
}
|
||||
if (id) {
|
||||
where += ' AND u.id = ?'
|
||||
params.push(Number(id))
|
||||
}
|
||||
if (role_id) {
|
||||
where += ' AND u.role_id = ?'
|
||||
params.push(Number(role_id))
|
||||
@@ -181,7 +204,9 @@ async function list(req, res) {
|
||||
}
|
||||
|
||||
const [[{ total }]] = await pool.query(
|
||||
`SELECT COUNT(*) AS total FROM users u ${where}`,
|
||||
`SELECT COUNT(*) AS total FROM users u
|
||||
LEFT JOIN employees e ON u.employee_id = e.id
|
||||
${where}`,
|
||||
params
|
||||
)
|
||||
|
||||
@@ -369,11 +394,20 @@ async function remove(req, res) {
|
||||
return res.status(400).json({ code: 400, message: '不能删除自己' })
|
||||
}
|
||||
|
||||
const [existing] = await pool.query('SELECT id FROM users WHERE id = ?', [id])
|
||||
const [existing] = await pool.query('SELECT id, role_id FROM users WHERE id = ?', [id])
|
||||
if (existing.length === 0) {
|
||||
return res.status(404).json({ code: 404, message: '用户不存在' })
|
||||
}
|
||||
|
||||
// 禁止删除最后一个管理员
|
||||
const [adminRole] = await pool.query('SELECT id FROM roles WHERE name = ?', ['admin'])
|
||||
if (adminRole.length > 0 && existing[0].role_id === adminRole[0].id) {
|
||||
const [[{ cnt }]] = await pool.query('SELECT COUNT(*) AS cnt FROM users WHERE role_id = ?', [adminRole[0].id])
|
||||
if (cnt <= 1) {
|
||||
return res.status(400).json({ code: 400, message: '不能删除最后一个管理员' })
|
||||
}
|
||||
}
|
||||
|
||||
await pool.query('DELETE FROM users WHERE id = ?', [id])
|
||||
res.json({ code: 0, message: 'ok' })
|
||||
} catch (e) {
|
||||
@@ -382,4 +416,4 @@ async function remove(req, res) {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { login, info, logout, changePassword, list, detail, create, update, remove }
|
||||
module.exports = { login, info, simpleList, logout, changePassword, list, detail, create, update, remove }
|
||||
|
||||
Reference in New Issue
Block a user