sqlite-web 0.7.2
gitea.db
issue
Create
Query
access
access_token
action
action_artifact
action_run
action_run_index
action_run_job
action_runner
action_runner_token
action_schedule
action_schedule_spec
action_task
action_task_output
action_task_step
action_tasks_version
action_variable
app_state
attachment
auth_token
badge
branch
collaboration
comment
commit_status
commit_status_index
commit_status_summary
commit_sync_log
commit_sync_status
dbfs_data
dbfs_meta
deploy_key
email_address
email_hash
external_login_user
follow
gpg_key
gpg_key_import
hook_task
issue
issue_assignees
issue_content_history
issue_dependency
issue_index
issue_label
issue_pin
issue_user
issue_watch
label
language_stat
lfs_lock
lfs_meta_object
login_source
milestone
mirror
notice
notification
oauth2_application
oauth2_authorization_code
oauth2_grant
org_user
package
package_blob
package_blob_upload
package_cleanup_rule
package_file
package_property
package_version
project
project_board
project_issue
protected_branch
protected_tag
public_key
pull_auto_merge
pull_request
push_mirror
reaction
release
renamed_branch
repo_archiver
repo_hidden_file
repo_indexer_status
repo_license
repo_redirect
repo_topic
repo_transfer
repo_unit
repository
review
review_state
secret
session
sqlite_sequence
star
stopwatch
system_setting
task
team
team_invite
team_repo
team_unit
team_user
topic
tracked_time
two_factor
upload
user
user_badge
user_blocking
user_open_id
user_redirect
user_setting
version
watch
webauthn_credential
webhook
Toggle helper tables
Structure
Content
Query
Insert
Drop
Import
Export
Update row 59 in issue
id
Primary key.
INTEGER NOT NULL
repo_id
INTEGER
index
INTEGER
poster_id
INTEGER
original_author
TEXT
original_author_id
INTEGER
name
🔍 代码审查报告:pc-260519 - Merge branch 'pc-260519' of gitea.g-hi.com:vodtest
TEXT
content
## 自动代码审查报告 **分支**: pc-260519 **提交**: `368847bc478ccecbb298e1d75a93bc2b402119a3` **时间**: 2026-04-14 10:21:19 --- ### 1. 总体评价 > **综合评分:4/10** > > **主要优点**: > - 前端 Vue 组件结构清晰,使用了 Element UI 标准组件。 > - 后端模型逻辑分层,尝试了业务逻辑封装。 > > **主要缺点**: > - **严重安全隐患**:PHP 代码中存在明显的 SQL 注入风险(字符串拼接 SQL);Vue 中存在 `v-html` 导致的 XSS 风险。 > - **代码重复率极高**:4 个 Vue 文件内容 95% 相同,仅配置项不同,严重违反 DRY 原则。 > - **可维护性差**:PHP 模型中存在大量重复逻辑、硬编码魔法数字、循环内查询数据库(N+1 问题)。 > - **规范缺失**:前端使用全局变量(`Vue.axios`, `layer`),后端混用命名风格,提交了构建产物(dist 文件)。 ### 2. 问题详情清单 | 严重等级 | 位置/行号 | 问题分类 | 问题描述 | 建议修改方案 | | :---: | :--- | :--- | :--- | :--- | | 🔴 严重 | `Ahead_bill_model.php`: 53, 64, 246 等 | 安全性 | **SQL 注入风险**:直接使用字符串拼接构建 `IN` 查询 (`... in (' . $unique_key_arr . ')`),若 `unique_key` 可控则极其危险。 | 使用框架提供的查询绑定(Query Binding)或预处理语句,避免手动拼接 SQL 字符串。 | | 🔴 严重 | `*_params_set.vue`: 109 | 安全性 | **XSS 风险**:`v-html="item.remark"` 直接渲染后端返回的 HTML,若后端未过滤恶意脚本,会导致跨站脚本攻击。 | 除非绝对必要且内容可信,否则使用 `{{ item.remark }}` 文本插值。若必须渲染 HTML,需在后端做严格的白名单过滤。 | | 🔴 严重 | `web/.../src/views/self_service_set/` | 可维护性 | **代码严重重复**:`KTV`, `bar`, `billiards`, `poker` 四个 Vue 文件代码几乎完全一致,仅 `operational_scene` 值不同。 | 提取为通用组件 `OperationalParamsSet.vue`,通过路由参数或 props 传入 `sceneType` 配置。 | | 🟡 警告 | `Ahead_bill_model.php`: 125, 369 | 性能 | **循环内查询数据库**:在 `foreach` 循环中加载模型并查询数据库 (`get_one`),会导致 N+1 查询问题,性能极差。 | 批量获取 ID 列表,一次性查询所有所需用户信息,然后在 PHP 内存中组装数据。 | | 🟡 警告 | `*_params_set.vue`: 全局 | 规范 | **全局依赖污染**:直接使用 `Vue.axios`, `layer`, `Vue.timeoutfun` 等全局变量,不利于模块化和测试。 | 使用 ES6 `import` 导入依赖,或通过 Vue 插件方式注入,避免隐式全局依赖。 | | 🟡 警告 | `*_params_set.vue`: 16 | 规范 | **可访问性缺失**:`<span>` 标签绑定点击事件,缺乏键盘导航支持(Tab 键无法聚焦)。 | 使用 `<button>` 标签或添加 `tabindex="0"` 及 `@keyup.enter` 事件。 | | 🟡 警告 | `Ahead_bill_model.php`: 13 | 规范 | **命名规范**:类属性 `$table_name` 使用蛇形命名,而方法 `get_list` 混合风格,且变量 `$tmp`, `$res` 语义不明。 | 统一遵循 PSR 标准,类属性建议 camelCase,变量名需语义化(如 `$orderAmountMap`)。 | | 🟢 建议 | `chunk-vendors...js` | 工程化 | **提交构建产物**:`dist` 目录下的压缩文件不应纳入版本控制或代码审查范围。 | 将 `dist` 加入 `.gitignore`,审查应针对 `src` 源代码。 | | 🟢 建议 | `*_params_set.vue`: 135 | 性能 | **深拷贝开销**:`JSON.parse(JSON.stringify(...))` 用于克隆对象,性能较低且丢失原型链。 | 使用结构化克隆 API 或lodash `cloneDeep`,或确保不需要深拷贝。 | ### 3. 优化代码示例 #### 3.1 前端 Vue 组件重构(解决重复代码问题) **原问题**:4 个文件内容重复,维护成本高。 **优化方案**:提取通用组件,通过配置驱动。 ```vue <!-- web/youc_business_operate_pc/src/views/self_service_set/OperationalParamsSet.vue --> <template> <div class="operational-params-set"> <!-- 门店列表 --> <div class="shop-list-panel" v-show="showIndex == 1"> <div class="page-title">{{ sceneConfig.name }}业务参数设置</div> <el-table :data="shop_list" v-loading="loading"> <!-- ... 表格列保持不变 ... --> <el-table-column :label="sceneConfig.name + '业务参数设置'"> <template slot-scope="scope"> <!-- 使用 button 提升可访问性 --> <el-button type="link" @click="handleSetClick(scope.row)">设置</el-button> <el-button type="link" @click="handleSyncClick(scope.row)">同步</el-button> </template> </el-table-column> </el-table> <!-- ... 分页保持不变 ... --> </div> <!-- 其他部分逻辑类似,将硬编码的 'KTV' 等替换为 sceneConfig --> <!-- 安全修复:移除 v-html --> <div class="red-tip" v-if="item.remark">{{ item.remark }}</div> </div> </template> <script> import axios from 'axios'; // 引入模块化 axios // 引入配置映射 const SCENE_CONFIG = { '1': { name: 'KTV', id: '1' }, '2': { name: '台球', id: '2' }, '3': { name: '棋牌', id: '3' }, '4': { name: '酒馆', id: '4' } }; export default { name: 'OperationalParamsSet', data() { return { // 从路由或 props 获取场景类型 operational_scene: this.$route.params.sceneType || '1', sceneConfig: SCENE_CONFIG[this.operational_scene] || SCENE_CONFIG['1'], // ... 其他数据 } }, methods: { // 使用 async/await 替代回调地狱 async getAllShopList() { try { const res = await axios.post('CommunityShop/getOperationalSceneShopList', { // ... 请求参数 }); if (res.data.response.result_code == "true") { this.all_shop_list = res.data.response.result.data; } else { this.$message.error(res.data.response.error_msg); } } catch (err) { this.$message.error('请求失败'); } } } } </script> ``` #### 3.2 后端 PHP 安全与性能优化 **原问题**:SQL 拼接注入风险 + 循环内查询。 **优化方案**:使用查询绑定 + 批量查询。 ```php // application/models/Ahead_bill_model.php // 优化前 (危险) // $sql = 'SELECT ... WHERE _unique_key in (' . $unique_key_arr . ') ...'; // 优化后 (安全 & 性能) public function get_list($where, $page, $page_size, $bill_where_in = array()) { // ... 前半部分代码保持不变 ... // 1. 收集所有 unique_key $unique_keys = array_column($bill_list, 'unique_key'); $tmp = []; if (!empty($unique_keys)) { // 2. 使用查询绑定防止 SQL 注入 (假设 CI 框架支持 query binding) // 如果框架不支持,至少需要对输入进行 intval 或 escape_str 处理 $placeholders = implode(',', array_fill(0, count($unique_keys), '?')); $sql = "SELECT _unique_key as unique_key, sum(if(_refund_amount>0 && _actual_pay<=_refund_amount,0,_prime_actual_pay-_refund_amount-_present_refund_amount)) as amount_total FROM `ahead_yc_order` WHERE _unique_key IN ($placeholders) AND ((_status in (1,4)) OR (_pay_platform=10 and _status=-1)) GROUP BY _unique_key"; // 执行带绑定的查询 $result = $this->db->query($sql, $unique_keys)->result_array(); foreach ($result as $v) { $tmp[$v['unique_key']]['amount_total'] = number_format($v['amount_total'], 2, '.', ''); } // 3. 批量查询支付日志 (同样避免循环查询) $sql_pay = "SELECT _unique_key as unique_key, sum(_refund_amount) as refund_amount, sum(IF(_pay_platform!=6,_actual_pay - _refund_amount,0)) as actual_pay FROM `ahead_pay_log` WHERE _unique_key IN ($placeholders) AND _status in (1, 4) AND _is_valid=1 GROUP BY _unique_key"; $result_pay = $this->db->query($sql_pay, $unique_keys)->result_array(); foreach ($result_pay as $v) { $tmp[$v['unique_key']]['actual_pay'] = number_format($v['actual_pay'], 2, '.', ''); $tmp[$v['unique_key']]['refund_amount'] = number_format($v['refund_amount'], 2, '.', ''); } } // 4. 批量获取挂账人信息 (避免循环内 load->model 和 query) $hanging_uids = array_filter(array_column($bill_list, 'hanging_account_uid')); $user_info_map = []; if (!empty($hanging_uids)) { $this->load->model('ahead_yc_merchant_user_model'); // 假设 get_list_by_ids 是批量查询方法,若无则需实现 $user_info_map = $this->ahead_yc_merchant_user_model->get_list_by_ids($hanging_uids); } foreach ($bill_list as &$v) { // ... 时间格式化 ... // 从内存 Map 获取数据,而非查询数据库 $v['hanging_account_username'] = $user_info_map[$v['hanging_account_uid']]['_name'] ?? ''; $v['hanging_account_worknumber'] = $user_info_map[$v['hanging_account_uid']]['_work_number'] ?? ''; // ... 其他逻辑 ... } unset($v); return $bill_list; } ``` ### 4. 总结与行动建议 1. **立即修复安全漏洞**: * **后端**:所有涉及用户输入拼接到 SQL 语句的地方,必须改为参数化查询(Prepared Statements)。 * **前端**:移除 `v-html`,除非有严格的 CSP 策略和后端内容过滤。 2. **重构前端重复代码**: * 将 4 个场景设置页面合并为 1 个通用组件,通过路由参数区分业务场景。这将减少 75% 的维护成本。 * 配置 ESLint 规则 `vue/no-v-html` 和 `vue/no-template-shadow` 强制规范。 3. **优化后端性能**: * 消除 `Ahead_bill_model.php` 中的循环数据库查询(N+1 问题),改为批量查询后内存组装。 * 清理 `dist` 目录,确保 Git 忽略构建产物,只审查源码。 4. **规范依赖管理**: * 前端移除对全局 `Vue.axios` 和 `layer` 的依赖,改为模块化导入 (`import axios from 'axios'`),便于 Tree-shaking 和版本管理。 **推荐 Lint 配置 (`.eslintrc.js`)**: ```javascript module.exports = { rules: { 'vue/no-v-html': 'error', // 禁止 v-html 'vue/require-component-is': 'error', 'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off', 'no-unused-vars': 'error' } } ``` --- *此 Issue 由代码审查服务自动创建*
TEXT
milestone_id
INTEGER
priority
INTEGER
is_closed
INTEGER
is_pull
INTEGER
num_comments
INTEGER
ref
TEXT
deadline_unix
INTEGER
created_unix
INTEGER
updated_unix
INTEGER
closed_unix
INTEGER
is_locked
INTEGER NOT NULL (default 0
content_version
INTEGER NOT NULL (default 0
time_estimate
INTEGER NOT NULL (default 0
Update
Cancel