xujunjie 1 rok temu
rodzic
commit
99f9c9f453

+ 2 - 3
src/pages/Detail/CommitAuditModal.js

@@ -740,12 +740,11 @@ function getDataValue(item) {
   return arr;
 }
 
-export default connect(({ xflow, detail, user, list }) => ({
+export default connect(({ xflow, detail, user }) => ({
   flowDetail: xflow.flowDetail,
   versionList: detail.versionList,
   currentUser: user.currentUser,
   userList: user.list,
   OSSData: detail.OSSData,
-  // 隐患:刷新页面后将会丢失projectList
-  projectList: list?.project?.list || [],
+  projectList: detail.project.list,
 }))(CommitAuditModal);

+ 1 - 1
src/pages/Detail/CurrentInfo.js

@@ -23,4 +23,4 @@ function CurrentInfo(props) {
   );
 }
 
-export default connect(({ list }) => ({ projectList: list?.project?.list || [] }))(CurrentInfo);
+export default connect(({ detail }) => ({ projectList: detail.project.list }))(CurrentInfo);

+ 3 - 0
src/pages/Detail/Index.js

@@ -497,6 +497,9 @@ function Detail(props) {
         project_id: projectId,
       },
     });
+    dispatch({
+      type: 'detail/queryProject',
+    });
 
     // dispatch({
     //   type: 'detail/queryListParentByUser',

+ 94 - 6
src/pages/Detail/LuckySheet.js

@@ -139,6 +139,9 @@ class LuckySheet extends React.Component {
             this.luckysheet.setCellFormat(0, 0, 'bg', '#fff');
           }, 100);
         },
+        workbookCreateAfter: options => {
+          this.luckysheet.refreshFormula();
+        },
       },
     };
     if (version) {
@@ -625,12 +628,13 @@ class LuckySheet extends React.Component {
     return comment;
   }
 
-  async goalSeek(type, goal,setting) {
+  async goalSeek(type, goal, setting) {
     let luckysheet = this.luckysheet;
     const sheet = this.luckysheet.getSheet({
-      name: '毛利概算'
-    })
+      name: '毛利概算',
+    });
     let order = sheet.order;
+    console.log(sheet);
 
     const fn = function(x) {
       return new Promise(resolve => {
@@ -656,17 +660,18 @@ class LuckySheet extends React.Component {
         });
       });
     };
+
     try {
       let defaultValue = luckysheet.getCellValue(9, 2, {
         order,
       });
       const result = await GoalSeek({
         goal,
-        fn,
-        fnParams: [defaultValue],
+        fn: fn2,
+        fnParams: [defaultValue, sheet.data, type],
         maxIterations: 1000,
         independentVariableIdx: 0,
-        ...setting
+        ...setting,
       });
       console.log(result);
     } catch (error) {
@@ -686,5 +691,88 @@ class LuckySheet extends React.Component {
     );
   }
 }
+function fn2(C10, data, type) {
+  let C50 = data[49][2].v || 0;
+  let C49 = data[48][2].v || 0;
+  let C20 = data[19][2].v || 0;
+  let C21 = data[20][2].v || 0;
+  let C9 = data[8][2].v || 0;
+  let C15 = data[14][2].v || 0;
+  let C16 = data[15][2].v || 0;
+  let C17 = data[16][2].v || 0;
+  let C18 = data[17][2].v || 0;
+  let C19 = data[18][2].v || 0;
+  let C51 = data[50][2].v || 0;
+
+  let G42 = data[41][6].v;
+  let G12 = data[11][6].v;
+  let G13 = data[12][6].v;
+  let G7 = data[6][6].v;
+  let G8 = data[7][6].v;
+  switch (type) {
+    case 1:
+      // 净利率
+      return C3() / C59();
+    case 2:
+      // 贡献毛利率
+      return C4() / C59();
+    case 3:
+      // 合同总价
+      return C59();
+  }
 
+  function C59() {
+    return C58() + C57() + C56() + C54();
+  }
+
+  function C4() {
+    return C3() + C50 + C49 + C48() + G42 + C43();
+  }
+  function C48() {
+    return C59 * G12;
+  }
+  function C58() {
+    return (C56() + C57()) * 0.12;
+  }
+  function C57() {
+    return (((C20 + C21) * C10) / (1 + G7)) * G7 - ((C20 + C21) / (1 + G8)) * G8;
+  }
+  function C56() {
+    return (
+      (((C15 + C16 + C17 + C18 + C19) * C10) / (1 + G7)) * G7 -
+      ((C15 + C16 + C17 + C18 + C19) / (1 + G7)) * G7
+    );
+  }
+  function C54() {
+    return SUM(2, [14, 20]) * C10;
+  }
+
+  function C3() {
+    return C55() - C53();
+  }
+  function C55() {
+    return C59 / (1 + G7);
+  }
+  function C53() {
+    return C52() - ((SUM(2, [14, 18]) / (1 + G7)) * G7 + (SUM(2, [19, 20]) / (1 + G8)) * G8);
+  }
+  function C52() {
+    return SUM(C15, C51);
+  }
+  function C43() {
+    return C59 * G13;
+  }
+  function C44() {
+    return C59 * C9;
+  }
+
+  function SUM(x, [y1, y2]) {
+    let total = 0;
+    for (let i = y1; i < y2; i++) {
+      const item = data[i][x];
+      total += item.v;
+    }
+    return total;
+  }
+}
 export default LuckySheet;

+ 2 - 2
src/pages/Detail/PsrControl.js

@@ -32,12 +32,12 @@ function PsrControl(props) {
       if (type == 3) {
         setting = {
           maxStep: 0.0001,
-          percentTolerance: 0.01,
+          customToleranceFn: res => Math.abs(res - value) < 10
         };
       } else {
         setting = {
           maxStep: 0.03,
-          percentTolerance: 1,
+          percentTolerance: 0.1,
         };
       }
       sheetRef.current.goalSeek(type, value, setting);

+ 10 - 6
src/pages/Detail/models/detail.js

@@ -1,16 +1,13 @@
 import {
   queryFlowInfo,
-  // commitSheet,
   querySheet,
   queryHistory,
-  // queryHistoryDetail,
   queryComment,
   addComment,
   createExcel,
   queryExcel,
   updateFlowInfo,
   submitAudit,
-  // approve,
   queryFiles,
   deleteFiles,
 } from '@/services/PurchaseList';
@@ -39,6 +36,7 @@ import {
   queryBindClassify,
   ChartTempOSSData,
 } from '@/services/boom';
+import { queryApproval } from '@/services/approval';
 import { queryRole } from '@/services/SysAdmin';
 import { setCurrentUser } from '@/utils/authority';
 import { queryProjectMenu } from '@/services/SysAdmin';
@@ -82,15 +80,21 @@ export default {
     classifyList: [],
     OSSData: {},
     excelFileList: [],
+    project: {
+      list: [],
+      pagination: false,
+    },
   },
 
   effects: {
-    *queryAuthority({ payload, callback }, { call, put }) {
-      const response = yield call(queryAuthority, payload);
+    *queryProject({ callback }, { call, put }) {
+      const response = yield call(queryApproval, { pageSize: 99999 });
       if (response) {
         yield put({
           type: 'save',
-          payload: { authority: response.data },
+          payload: {
+            project: response.data,
+          },
         });
       }
     },

+ 65 - 35
src/utils/GoalSeek.js

@@ -2,16 +2,17 @@ const IsNanError = TypeError('resulted in NaN');
 const FailedToConvergeError = Error('failed to converge');
 const InvalidInputsError = Error('invalid inputs');
 
-export default async function GoalSeek({
-  fn,
-  fnParams,
-  percentTolerance,
-  customToleranceFn,
-  maxIterations,
-  maxStep,
-  goal,
-  independentVariableIdx,
-}) {
+export default async function GoalSeek(options) {
+  const {
+    fn,
+    fnParams,
+    percentTolerance,
+    customToleranceFn,
+    maxIterations,
+    maxStep,
+    goal,
+    independentVariableIdx,
+  } = options;
   if (typeof customToleranceFn !== 'function') {
     if (!percentTolerance) {
       throw InvalidInputsError;
@@ -19,49 +20,78 @@ export default async function GoalSeek({
   }
   let g;
   let y;
-  let y1;
-  let oldGuess;
+  let oldY = 0;
+  let oldGuess = fnParams[independentVariableIdx];
   let newGuess;
   let res;
+  let max;
+  let min;
   const absoluteTolerance = ((percentTolerance || 0) / 100) * goal;
+  
+  async function getMin(minGuest) {
+    let copyParams = [...fnParams]
+    copyParams[independentVariableIdx] = minGuest
+    res = await fn(...copyParams);
+    if (res > goal) {
+      minGuest -= oldGuess / 2;
+      await getMin(minGuest);
+    }
+    return minGuest;
+  }
+
+  async function getMax(maxGuest) {
+    let copyParams = [...fnParams]
+    copyParams[independentVariableIdx] = maxGuest
+    res = await fn(...copyParams);
+    if (res < goal) {
+      maxGuest += oldGuess / 2;
+      await getMax(maxGuest);
+    }
+    return maxGuest;
+  }
   // iterate through the guesses
   for (let i = 0; i < maxIterations; i++) {
     // define the root of the function as the error
     res = await fn(...fnParams);
     y = res - goal;
     if (isNaN(y)) throw IsNanError;
-    // was our initial guess a good one?
+    // 判断是否满足条件
     if (typeof customToleranceFn !== 'function') {
       if (Math.abs(y) <= Math.abs(absoluteTolerance)) return fnParams[independentVariableIdx];
     } else {
       if (customToleranceFn(res)) return fnParams[independentVariableIdx];
     }
-    // set the new guess, correcting for maxStep
+    // 获取要改变的变量
     oldGuess = fnParams[independentVariableIdx];
-    newGuess = oldGuess + y;
-    if (Math.abs(newGuess - oldGuess) > maxStep) {
-      if (newGuess > oldGuess) {
-        newGuess = oldGuess + maxStep;
-      } else {
-        newGuess = oldGuess - maxStep;
+
+    // newGuess = oldGuess + y;
+    // if (Math.abs(newGuess - oldGuess) > maxStep) {
+    //   if (newGuess > oldGuess) {
+    //     newGuess = oldGuess + maxStep;
+    //   } else {
+    //     newGuess = oldGuess - maxStep;
+    //   }
+    // }
+    // 获取最大值和最小值
+    if (y > 0) {
+      max = oldGuess;
+      if (!min) {
+        min = await getMin(oldGuess / 2);
       }
-    }
-    fnParams[independentVariableIdx] = newGuess;
-    // re-run the fn with the new guess
-    y1 = (await fn(...fnParams)) - goal;
-    if (isNaN(y1)) throw IsNanError;
-    // calculate the error
-    g = (y1 - y) / y;
-    if (g === 0) g = 0.0001;
-    // set the new guess based on the error, correcting for maxStep
-    newGuess = oldGuess - y / g;
-    if (maxStep && Math.abs(newGuess - oldGuess) > maxStep) {
-      if (newGuess > oldGuess) {
-        newGuess = oldGuess + maxStep;
-      } else {
-        newGuess = oldGuess - maxStep;
+    } else {
+      min = oldGuess;
+      if (!max) {
+        max = await getMax(oldGuess * 2);
       }
     }
+    // if(oldY) {
+    //   if(y > oldY) {
+
+    //   }
+    // }
+    // oldY = y;
+    // 利用二分法查询
+    newGuess = (min + max) / 2;
     fnParams[independentVariableIdx] = newGuess;
   }
   // done with iterations, and we failed to converge