| app/APP配置数据库化说明.md | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| app/App.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| app/api/appConfig.js | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| app/config.js | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| app/pagesTask/detail.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| ruoyi-admin/src/main/java/com/ruoyi/web/controller/app/AppConfigController.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| sql/app_config.sql | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
app/APPÅäÖÃÊý¾Ý¿â»¯ËµÃ÷.md
New file @@ -0,0 +1,173 @@ # APPé ç½®ä»æ°æ®åºè¯»ååè½è¯´æ ## æ¦è¿° å°APPçåè½å¼å ³é ç½®ä»æ¬å° `config.js` æä»¶æ¹ä¸ºä»æ°æ®åºå¨æè¯»åï¼å®ç°åå°å¯é ç½®å管çã ## å®ç°å 容 ### 1. å端å®ç° #### 1.1 å建é ç½®æ§å¶å¨ **æä»¶**: `ruoyi-admin/src/main/java/com/ruoyi/web/controller/app/AppConfigController.java` æä¾ä¸¤ä¸ªæ¥å£ï¼ - `GET /app/config/features` - è·ååè½å¼å ³é ç½® - `GET /app/config/all` - è·å宿´APPé ç½® ç¹ç¹ï¼ - æ éæéæ ¡éªï¼ææç»å½ç¨æ·é½å¯è®¿é® - èªå¨å°é ç½®å¼è½¬æ¢ä¸ºå¸å°ç±»å #### 1.2 æ°æ®åºé ç½® **æä»¶**: `sql/app_config.sql` æå ¥ä¸¤æ¡é 置记å½ï¼ ```sql -- 就绪æé®é ç½® config_key: app.feature.showAssigneeReadyButton config_value: true/false -- 强å¶å®ææé®é ç½® config_key: app.feature.showForceCompleteButton config_value: true/false ``` ### 2. å端å®ç° #### 2.1 APIæ¥å£æä»¶ **æä»¶**: `app/api/appConfig.js` å°è£ é ç½®è·åæ¥å£ï¼ - `getAppFeatures()` - è·ååè½å¼å ³ - `getAppConfig()` - è·å宿´é ç½® #### 2.2 åºç¨å¯å¨å è½½ **æä»¶**: `app/App.vue` ä¿®æ¹é ç½®å è½½é»è¾ï¼ 1. **åºç¨å¯å¨æ¶**ï¼ - å ä½¿ç¨æ¬å°é»è®¤é ç½®ï¼config.jsï¼ - 妿已ç»å½ï¼ä»æå¡å¨å è½½é 置并è¦çæ¬å°é ç½® 2. **ç¨æ·ç»å½å**ï¼ - çå¬ `user-login` äºä»¶ - èªå¨ä»æå¡å¨å è½½ææ°é ç½® 3. **é ç½®åå¹¶çç¥**ï¼ - æå¡å¨é ç½®ä¼å 级é«äºæ¬å°é ç½® - æ¬å°é ç½®ä½ä¸ºé»è®¤å¼ï¼ç½ç»å¤±è´¥æ¶ä½¿ç¨ï¼ #### 2.3 æ¬å°é ç½®ä¿ç **æä»¶**: `app/config.js` ä¿ç features é ç½®ä½ä¸ºé»è®¤å¼ï¼ ```javascript features: { showAssigneeReadyButton: true, showForceCompleteButton: true } ``` ### 3. é 置项说æ | é ç½®é® | 说æ | å¯éå¼ | é»è®¤å¼ | |-------|------|--------|--------| | app.feature.showAssigneeReadyButton | æ¯å¦æ¾ç¤ºæ§è¡äººå°±ç»ªæé® | true/false | true | | app.feature.showForceCompleteButton | æ¯å¦æ¾ç¤ºå¼ºå¶å®ææé® | true/false | true | ## ä½¿ç¨æ¹å¼ ### åå°é ç½® 1. **éè¿åå°ç®¡ççé¢**ï¼ - ç»å½åå°ç®¡çç³»ç» - è¿å ¥ãç³»ç»ç®¡çã->ãåæ°è®¾ç½®ã - æç´¢ "APP-æ¾ç¤º" æ¾å°ç¸å ³é ç½® - ä¿®æ¹ config_value 为 `true` æ `false` 2. **ç´æ¥ä¿®æ¹æ°æ®åº**ï¼ ```sql -- éè强å¶å®ææé® UPDATE sys_config SET config_value = 'false' WHERE config_key = 'app.feature.showForceCompleteButton'; -- æ¾ç¤ºå¼ºå¶å®ææé® UPDATE sys_config SET config_value = 'true' WHERE config_key = 'app.feature.showForceCompleteButton'; ``` ### APPçææ¶æº é 置修æ¹åï¼APPå¨ä»¥ä¸æ åµä¼è·åææ°é ç½®ï¼ 1. ç¨æ·éæ°ç»å½ 2. åºç¨éæ°å¯å¨ 3. ä»åå°åæ¢ååå°ï¼å¦æå·²ç»å½ï¼ ## é ç½®ä¼å 级 ``` æå¡å¨é ç½® > æ¬å°é»è®¤é ç½® ``` - **æå¡å¨é ç½®å¯ç¨æ¶**ï¼ä½¿ç¨æ°æ®åºä¸çé ç½® - **æå¡å¨é ç½®å 载失败**ï¼ä½¿ç¨ config.js ä¸çé»è®¤é ç½® - **ç¨æ·æªç»å½**ï¼ä½¿ç¨ config.js ä¸çé»è®¤é ç½® ## æ©å±è¯´æ ### æ·»å æ°çé 置项 1. **æ°æ®åºæ·»å é ç½®**ï¼ ```sql INSERT INTO sys_config (config_name, config_key, config_value, config_type, create_by, create_time, remark) VALUES ('APP-æ°åè½å¼å ³', 'app.feature.newFeature', 'true', 'N', 'admin', sysdate(), 'æ°åè½å¼å ³è¯´æ'); ``` 2. **å端添å 读åé»è¾**ï¼ ```java // AppConfigController.java String newFeature = configService.selectConfigByKey("app.feature.newFeature"); features.put("newFeature", "true".equalsIgnoreCase(newFeature)); ``` 3. **å端config.jsæ·»å é»è®¤å¼**ï¼ ```javascript features: { showAssigneeReadyButton: true, showForceCompleteButton: true, newFeature: true // æ°å¢ } ``` 4. **页é¢ä½¿ç¨é ç½®**ï¼ ```javascript // å¨ methods 䏿·»å å¤ææ¹æ³ showNewFeature() { return !!(config && config.features && config.features.newFeature) } // 卿¨¡æ¿ä¸ä½¿ç¨ <button v-if="showNewFeature()">æ°åè½æé®</button> ``` ## 注æäºé¡¹ 1. **é ç½®ç¼å**ï¼è¥ä¾æ¡æ¶å¯¹ sys_config 表æç¼åæºå¶ï¼ä¿®æ¹é ç½®åå¯è½éè¦å·æ°ç¼å 2. **é ç½®æ ¼å¼**ï¼config_value åªæ¯æå符串ï¼å端ä¼è½¬æ¢ä¸ºå¸å°å¼ 3. **å ¼å®¹æ§**ï¼ä¿çæ¬å°é»è®¤é 置确ä¿ç½ç»å¼å¸¸æ¶åè½å¯ç¨ 4. **å®å ¨æ§**ï¼é ç½®æ¥å£æ éæéï¼ç¡®ä¿ä¸æ´é²ææä¿¡æ¯ ## ç¸å ³æä»¶æ¸ å ### å端 - `ruoyi-admin/src/main/java/com/ruoyi/web/controller/app/AppConfigController.java` - é ç½®æ§å¶å¨ - `sql/app_config.sql` - é ç½®æ°æ®SQL ### å端 - `app/api/appConfig.js` - APIæ¥å£ - `app/App.vue` - åºç¨å¯å¨é ç½®å è½½ - `app/config.js` - æ¬å°é»è®¤é ç½® - `app/pagesTask/detail.vue` - ä»»å¡è¯¦æ 页ï¼ä½¿ç¨é ç½®ï¼ app/App.vue
@@ -5,6 +5,7 @@ import { getUnreadCount } from '@/api/message' import storage from '@/utils/storage' import { redirectToLoginByEnvironment } from '@/utils/wechat' import { getAppFeatures } from '@/api/appConfig' export default { data() { @@ -29,6 +30,8 @@ this.lastToken = token this.updateUnreadMessageBadge() // this.startMessagePolling() // å è½½æå¡å¨é ç½® this.loadServerConfig() } }) @@ -91,8 +94,37 @@ // 注æï¼ä¸å¨åºç¨å¯å¨æ¶èªå¨å¯å¨è½®è¯¢ // åªæå¨ç¨æ·ä¸»å¨ç»å½æååæå¯å¨ï¼éè¿ user-login äºä»¶è§¦åï¼ }, // åå§åé ç½®ï¼åå¹¶æ¬å°é ç½®åæå¡å¨é ç½® initConfig() { // å ä½¿ç¨æ¬å°é»è®¤é ç½® this.globalData.config = config // å¦æç¨æ·å·²ç»å½ï¼å°è¯å è½½æå¡å¨é ç½® if (getToken()) { this.loadServerConfig() } else { console.log('ç¨æ·æªç»å½ï¼ä½¿ç¨æ¬å°é»è®¤é ç½®') } }, // 仿å¡å¨å è½½é ç½® loadServerConfig() { getAppFeatures().then(response => { console.log('å è½½æå¡å¨é ç½®æå:', response.data) // åå¹¶é ç½®ï¼æå¡å¨é ç½®è¦çæ¬å°é ç½® if (response.data) { this.globalData.config.features = Object.assign({}, this.globalData.config.features || {}, response.data ) // æ´æ°å ¨å±config对象ï¼ç¡®ä¿å ¶ä»å°æ¹ä¹è½è·åå°ææ°é ç½® config.features = this.globalData.config.features } }).catch(error => { console.error('å è½½æå¡å¨é 置失败:', error) console.log('ä½¿ç¨æ¬å°é»è®¤é ç½®') }) }, // æ£æ¥ç»å½ç¶æå¹¶èªå¨è·³è½¬å°åéçç»å½é¡µé¢ checkLoginAndRedirect(options) { app/api/appConfig.js
New file @@ -0,0 +1,21 @@ import request from '@/utils/request' /** * è·åAPPåè½å¼å ³é ç½® */ export function getAppFeatures() { return request({ url: '/app/config/features', method: 'get' }) } /** * è·å宿´çAPPé ç½® */ export function getAppConfig() { return request({ url: '/app/config/all', method: 'get' }) } app/config.js
@@ -63,7 +63,9 @@ // åè½å¼å ³ features: { // æ¯å¦æ¾ç¤ºæ§è¡äººâ就绪âæé® showAssigneeReadyButton: true // æ¯å¦æ¾ç¤ºæ§è¡äºº"就绪"æé® showAssigneeReadyButton: true, // æ¯å¦æ¾ç¤º"强å¶å®æ"æé® showForceCompleteButton: true } } app/pagesTask/detail.vue
@@ -470,6 +470,7 @@ åæ¶ </button> <button v-if="showForceCompleteFeature() && taskDetail.taskStatus === 'PENDING'" class="action-btn force-complete" @click="showForceCompleteTimeDialog()" > @@ -1421,11 +1422,16 @@ console.log('éä»¶å 餿å:', attachmentId) }, // æ¯å¦æ¾ç¤ºâ就绪âåè½ï¼é ç½®å¼å ³ï¼ // æ¯å¦æ¾ç¤º"就绪"åè½ï¼é ç½®å¼å ³ï¼ showAssigneeReadyFeature() { return !!(config && config.features && config.features.showAssigneeReadyButton) }, // æ¯å¦æ¾ç¤º"强å¶å®æ"åè½ï¼é ç½®å¼å ³ï¼ showForceCompleteFeature() { return !!(config && config.features && config.features.showForceCompleteButton) }, // å½åç¨æ·æ¯å¦ä¸ºè¯¥æ§è¡äºº isAssigneeSelf(assignee) { const userId = this.$store && this.$store.state && this.$store.state.user && this.$store.state.user.userId ruoyi-admin/src/main/java/com/ruoyi/web/controller/app/AppConfigController.java
New file @@ -0,0 +1,66 @@ package com.ruoyi.web.controller.app; import java.util.HashMap; import java.util.Map; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import com.ruoyi.common.core.controller.BaseController; import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.system.service.ISysConfigService; /** * APPé ç½®æ§å¶å¨ * * @author ruoyi */ @RestController @RequestMapping("/app/config") public class AppConfigController extends BaseController { @Autowired private ISysConfigService configService; /** * è·åAPPåè½å¼å ³é ç½® * ä¸éè¦æéæ ¡éªï¼ææç»å½ç¨æ·é½å¯ä»¥è®¿é® */ @GetMapping("/features") public AjaxResult getFeatures() { Map<String, Object> features = new HashMap<>(); // 读å就绪æé®é ç½® String showAssigneeReadyButton = configService.selectConfigByKey("app.feature.showAssigneeReadyButton"); features.put("showAssigneeReadyButton", "true".equalsIgnoreCase(showAssigneeReadyButton)); // 读å强å¶å®ææé®é ç½® String showForceCompleteButton = configService.selectConfigByKey("app.feature.showForceCompleteButton"); features.put("showForceCompleteButton", "true".equalsIgnoreCase(showForceCompleteButton)); return success(features); } /** * è·å宿´çAPPé ç½® * å æ¬baseUrlãappInfoãfeaturesç */ @GetMapping("/all") public AjaxResult getAllConfig() { Map<String, Object> config = new HashMap<>(); // åè½å¼å ³é ç½® Map<String, Object> features = new HashMap<>(); String showAssigneeReadyButton = configService.selectConfigByKey("app.feature.showAssigneeReadyButton"); features.put("showAssigneeReadyButton", "true".equalsIgnoreCase(showAssigneeReadyButton)); String showForceCompleteButton = configService.selectConfigByKey("app.feature.showForceCompleteButton"); features.put("showForceCompleteButton", "true".equalsIgnoreCase(showForceCompleteButton)); config.put("features", features); return success(config); } } sql/app_config.sql
New file @@ -0,0 +1,8 @@ -- APPåè½å¼å ³é ç½® -- æå ¥å°±ç»ªæé®é ç½® INSERT INTO sys_config (config_name, config_key, config_value, config_type, create_by, create_time, remark) VALUES ('APP-æ¾ç¤ºæ§è¡äººå°±ç»ªæé®', 'app.feature.showAssigneeReadyButton', 'true', 'N', 'admin', sysdate(), 'æ§å¶APPä»»å¡è¯¦æ 页æ¯å¦æ¾ç¤ºæ§è¡äººå°±ç»ªæé®ï¼trueæ¾ç¤ºï¼falseéèï¼'); -- æå ¥å¼ºå¶å®ææé®é ç½® INSERT INTO sys_config (config_name, config_key, config_value, config_type, create_by, create_time, remark) VALUES ('APP-æ¾ç¤ºå¼ºå¶å®ææé®', 'app.feature.showForceCompleteButton', 'true', 'N', 'admin', sysdate(), 'æ§å¶APPä»»å¡è¯¦æ 页æ¯å¦æ¾ç¤ºå¼ºå¶å®ææé®ï¼trueæ¾ç¤ºï¼falseéèï¼');