Commit 3f8b942fd5773384cf463fe3ae90ee30b4767545

Authored by “wangming”
1 parent 910e21a0

feat: 添加业绩类型字段并修复转卡业绩计算逻辑

- 在开单品项表、健康师业绩表、科技老师业绩表、消耗品项表、业绩表等10个表中添加F_PerformanceType字段
- 修复转卡时健康师和科技部老师业绩计算逻辑,按原业绩比例计算而非直接复制
- 修复退卡明细表F_SourceType字段赋值错误(使用品项分类而非开单类型)
- 添加SQL脚本用于添加业绩类型字段和更新历史数据
- 业绩类型根据品项表(lq_xmzl)的fl3字段设置
antis-ncc-admin/src/views/lqHytkHytk/Form.vue
1 <template> 1 <template>
2 - <el-dialog :title="!dataForm.id ? '新建' : isDetail ? '详情':'编辑'" :close-on-click-modal="false" :visible.sync="visible" class="NCC-dialog NCC-dialog_center" lock-scroll width="90%">  
3 - <el-row :gutter="15" class="" >  
4 - <el-form ref="elForm" :model="dataForm" size="small" label-width="100px" label-position="right" :disabled="!!isDetail" :rules="rules">  
5 - <el-col :span="8" v-if="false" >  
6 - <el-form-item label="退卡编号" prop="id">  
7 - <el-input v-model="dataForm.id" placeholder="请输入" clearable :style='{"width":"100%"}' >  
8 - </el-input>  
9 - </el-form-item>  
10 - </el-col>  
11 - <el-col :span="8">  
12 - <el-form-item label="门店" prop="md" required>  
13 - <el-select v-model="dataForm.md" placeholder="请选择" clearable :style='{"width":"100%"}' filterable @change="handleMdChange">  
14 - <el-option v-for="(item, index) in mdOptions" :key="index" :label="item.fullName" :value="item.id" ></el-option>  
15 - </el-select>  
16 - </el-form-item>  
17 - </el-col>  
18 - <el-col :span="8"> 2 + <el-dialog :title="!dataForm.id ? '新建' : isDetail ? '详情' : '编辑'" :close-on-click-modal="false"
  3 + :visible.sync="visible" class="NCC-dialog NCC-dialog_center" lock-scroll width="90%">
  4 + <el-row :gutter="15" class="">
  5 + <el-form ref="elForm" :model="dataForm" size="small" label-width="100px" label-position="right"
  6 + :disabled="!!isDetail" :rules="rules">
  7 + <el-col :span="8" v-if="false">
  8 + <el-form-item label="退卡编号" prop="id">
  9 + <el-input v-model="dataForm.id" placeholder="请输入" clearable :style='{ "width": "100%" }'>
  10 + </el-input>
  11 + </el-form-item>
  12 + </el-col>
  13 + <el-col :span="8">
  14 + <el-form-item label="门店" prop="md" required>
  15 + <el-select v-model="dataForm.md" placeholder="请选择" clearable :style='{ "width": "100%" }'
  16 + filterable @change="handleMdChange">
  17 + <el-option v-for="(item, index) in mdOptions" :key="index" :label="item.fullName"
  18 + :value="item.id"></el-option>
  19 + </el-select>
  20 + </el-form-item>
  21 + </el-col>
  22 + <el-col :span="8">
19 <el-form-item label="退卡时间" prop="tksj"> 23 <el-form-item label="退卡时间" prop="tksj">
20 - <el-date-picker v-model="dataForm.tksj" placeholder="请选择" clearable :style='{"width":"100%"}' type='date' format="yyyy-MM-dd" value-format="timestamp" > 24 + <el-date-picker v-model="dataForm.tksj" placeholder="请选择" clearable :style='{ "width": "100%" }'
  25 + type='date' format="yyyy-MM-dd" value-format="timestamp">
21 </el-date-picker> 26 </el-date-picker>
22 </el-form-item> 27 </el-form-item>
23 </el-col> 28 </el-col>
24 - <el-col :span="8" v-if="false">  
25 - <el-form-item label="门店编号" prop="mdbh">  
26 - <el-input v-model="dataForm.mdbh" placeholder="自动填充" clearable readonly :style='{"width":"100%"}' >  
27 - </el-input>  
28 - </el-form-item>  
29 - </el-col>  
30 - <el-col :span="8" v-if="false">  
31 - <el-form-item label="门店名称" prop="mdmc">  
32 - <el-input v-model="dataForm.mdmc" placeholder="自动填充" clearable readonly :style='{"width":"100%"}' >  
33 - </el-input>  
34 - </el-form-item>  
35 - </el-col>  
36 - <el-col :span="8">  
37 - <el-form-item label="会员" prop="hy" required>  
38 - <el-select v-model="dataForm.hy" placeholder="请选择" clearable :style='{"width":"100%"}' filterable @change="handleHyChange">  
39 - <el-option v-for="(item, index) in hyOptions" :key="index" :label="item.fullName" :value="item.id" ></el-option>  
40 - </el-select>  
41 - </el-form-item>  
42 - </el-col>  
43 - <el-col :span="8" v-if="false">  
44 - <el-form-item label="会员姓名" prop="hymc">  
45 - <el-input v-model="dataForm.hymc" placeholder="自动填充" clearable readonly :style='{"width":"100%"}' >  
46 - </el-input>  
47 - </el-form-item>  
48 - </el-col>  
49 - <el-col :span="8" v-if="false">  
50 - <el-form-item label="会员账号" prop="hyzh">  
51 - <el-input v-model="dataForm.hyzh" placeholder="自动填充" clearable readonly :style='{"width":"100%"}' >  
52 - </el-input>  
53 - </el-form-item>  
54 - </el-col>  
55 - <el-col :span="8">  
56 - <el-form-item label="退款金额" prop="tkje">  
57 - <el-input v-model="dataForm.tkje" placeholder="自动计算" clearable readonly :style='{"width":"100%"}'>  
58 - <template slot="append">元</template>  
59 - </el-input>  
60 - </el-form-item>  
61 - </el-col>  
62 - <el-col :span="8">  
63 - <el-form-item label="手工费用" prop="sgfy">  
64 - <el-input v-model="dataForm.sgfy" placeholder="自动计算" clearable readonly :style='{"width":"100%"}'>  
65 - <template slot="append">元</template>  
66 - </el-input>  
67 - </el-form-item>  
68 - </el-col>  
69 - <el-col :span="16"></el-col>  
70 - <el-col :span="24" v-if="false" >  
71 - <el-form-item label="退卡品项" prop="tkpx">  
72 - <el-input v-model="dataForm.tkpx" placeholder="请输入" clearable :style='{"width":"100%"}' >  
73 - </el-input>  
74 - </el-form-item>  
75 - </el-col>  
76 - <el-col :span="24" v-if="dataForm.hy && pxOptions.length > 0">  
77 - <el-form-item label="会员剩余品项" label-width="100px">  
78 - <div class="member-remaining-items">  
79 - <div class="remaining-items-header">  
80 - <span class="items-title">会员剩余品项列表 ({{ pxOptions.length }} 个)</span>  
81 - </div>  
82 - <div class="remaining-items-list">  
83 - <div v-for="(item, index) in pxOptions" :key="index" class="remaining-item-row" :class="{ 'disabled': item.RemainingCount <= 0 }">  
84 - <div class="item-name">{{ item.fullName }}</div>  
85 - <div class="item-price">¥{{ item.ItemPrice || 0 }}</div>  
86 - <div class="item-quantity" :class="{ 'zero': item.RemainingCount <= 0 }">  
87 - 剩余: {{ item.RemainingCount || 0 }}  
88 - </div>  
89 - <div class="item-source">{{ item.sourceType || '购买' }}</div> 29 + <el-col :span="8" v-if="false">
  30 + <el-form-item label="门店编号" prop="mdbh">
  31 + <el-input v-model="dataForm.mdbh" placeholder="自动填充" clearable readonly
  32 + :style='{ "width": "100%" }'>
  33 + </el-input>
  34 + </el-form-item>
  35 + </el-col>
  36 + <el-col :span="8" v-if="false">
  37 + <el-form-item label="门店名称" prop="mdmc">
  38 + <el-input v-model="dataForm.mdmc" placeholder="自动填充" clearable readonly
  39 + :style='{ "width": "100%" }'>
  40 + </el-input>
  41 + </el-form-item>
  42 + </el-col>
  43 + <el-col :span="8">
  44 + <el-form-item label="会员" prop="hy" required>
  45 + <el-select v-model="dataForm.hy" placeholder="请选择" clearable :style='{ "width": "100%" }'
  46 + filterable @change="handleHyChange">
  47 + <el-option v-for="(item, index) in hyOptions" :key="index" :label="item.fullName"
  48 + :value="item.id"></el-option>
  49 + </el-select>
  50 + </el-form-item>
  51 + </el-col>
  52 + <el-col :span="8" v-if="false">
  53 + <el-form-item label="会员姓名" prop="hymc">
  54 + <el-input v-model="dataForm.hymc" placeholder="自动填充" clearable readonly
  55 + :style='{ "width": "100%" }'>
  56 + </el-input>
  57 + </el-form-item>
  58 + </el-col>
  59 + <el-col :span="8" v-if="false">
  60 + <el-form-item label="会员账号" prop="hyzh">
  61 + <el-input v-model="dataForm.hyzh" placeholder="自动填充" clearable readonly
  62 + :style='{ "width": "100%" }'>
  63 + </el-input>
  64 + </el-form-item>
  65 + </el-col>
  66 + <el-col :span="8">
  67 + <el-form-item label="退款金额" prop="tkje">
  68 + <el-input v-model="dataForm.tkje" placeholder="自动计算" clearable readonly
  69 + :style='{ "width": "100%" }'>
  70 + <template slot="append">元</template>
  71 + </el-input>
  72 + </el-form-item>
  73 + </el-col>
  74 + <el-col :span="8">
  75 + <el-form-item label="手工费用" prop="sgfy">
  76 + <el-input v-model="dataForm.sgfy" placeholder="自动计算" clearable readonly
  77 + :style='{ "width": "100%" }'>
  78 + <template slot="append">元</template>
  79 + </el-input>
  80 + </el-form-item>
  81 + </el-col>
  82 + <el-col :span="16"></el-col>
  83 + <el-col :span="24" v-if="false">
  84 + <el-form-item label="退卡品项" prop="tkpx">
  85 + <el-input v-model="dataForm.tkpx" placeholder="请输入" clearable :style='{ "width": "100%" }'>
  86 + </el-input>
  87 + </el-form-item>
  88 + </el-col>
  89 + <el-col :span="24" v-if="dataForm.hy && pxOptions.length > 0">
  90 + <el-form-item label="会员剩余品项" label-width="100px">
  91 + <div class="member-remaining-items">
  92 + <div class="remaining-items-header">
  93 + <span class="items-title">会员剩余品项列表 ({{ pxOptions.length }} 个)</span>
  94 + </div>
  95 + <div class="remaining-items-list">
  96 + <div v-for="(item, index) in pxOptions" :key="index" class="remaining-item-row"
  97 + :class="{ 'disabled': item.RemainingCount <= 0 }">
  98 + <div class="item-name">{{ item.fullName }}</div>
  99 + <div class="item-price">¥{{ item.ItemPrice || 0 }}</div>
  100 + <div class="item-quantity" :class="{ 'zero': item.RemainingCount <= 0 }">
  101 + 剩余: {{ item.RemainingCount || 0 }}
90 </div> 102 </div>
  103 + <div class="item-source">{{ item.sourceType || '购买' }}</div>
91 </div> 104 </div>
92 </div> 105 </div>
93 - </el-form-item>  
94 - </el-col>  
95 - <el-col :span="24"> 106 + </div>
  107 + </el-form-item>
  108 + </el-col>
  109 + <el-col :span="24">
96 <el-form-item label-width="0"> 110 <el-form-item label-width="0">
97 <div class="table-header"> 111 <div class="table-header">
98 <span class="table-title">品项明细</span> 112 <span class="table-title">品项明细</span>
99 - <el-button v-if="!dataForm.id" type="warning" size="mini" icon="el-icon-plus" @click="addHandleLqXhPxmxEntityList()">新增品项</el-button> 113 + <el-button v-if="!dataForm.id" type="warning" size="mini" icon="el-icon-plus"
  114 + @click="addHandleLqXhPxmxEntityList()">新增品项</el-button>
100 </div> 115 </div>
101 - 116 +
102 <!-- 品项列表 --> 117 <!-- 品项列表 -->
103 <div class="px-list-container"> 118 <div class="px-list-container">
104 <div v-for="(px, pxIndex) in dataForm.lqHytkMxList" :key="pxIndex" class="px-item"> 119 <div v-for="(px, pxIndex) in dataForm.lqHytkMxList" :key="pxIndex" class="px-item">
@@ -106,16 +121,20 @@ @@ -106,16 +121,20 @@
106 <div class="px-basic-info"> 121 <div class="px-basic-info">
107 <div class="px-item-header"> 122 <div class="px-item-header">
108 <span class="px-item-title">品项明细</span> 123 <span class="px-item-title">品项明细</span>
109 - <el-button v-if="!dataForm.id"size="mini" type="danger" icon="el-icon-delete" @click="handleDelLqXhPxmxEntityList(pxIndex)">删除</el-button> 124 + <el-button v-if="!dataForm.id" size="mini" type="danger" icon="el-icon-delete"
  125 + @click="handleDelLqXhPxmxEntityList(pxIndex)">删除</el-button>
110 </div> 126 </div>
111 - 127 +
112 <!-- 品项选择 --> 128 <!-- 品项选择 -->
113 <div class="px-select-row"> 129 <div class="px-select-row">
114 - <el-select v-model="px.pxid" placeholder="请选择品项" clearable filterable @change="handlePxChange(pxIndex, px)" style="width: 200px;">  
115 - <el-option v-for="(item, index) in pxOptions" :key="index" :label="item.fullName+'(剩余: '+(item.RemainingCount || 0)+',类型:'+item.sourceType+')'" :value="item.pxid" :disabled="item.disabled"></el-option> 130 + <el-select v-model="px.pxid" placeholder="请选择品项" clearable filterable
  131 + @change="handlePxChange(pxIndex, px)" style="width: 200px;">
  132 + <el-option v-for="(item, index) in pxOptions" :key="index"
  133 + :label="item.fullName + '(剩余: ' + (item.RemainingCount || 0) + ',类型:' + item.sourceType + ')'"
  134 + :value="item.pxid" :disabled="item.disabled"></el-option>
116 </el-select> 135 </el-select>
117 </div> 136 </div>
118 - 137 +
119 <!-- 品项详细信息 --> 138 <!-- 品项详细信息 -->
120 <div class="px-detail-info" v-if="px.px"> 139 <div class="px-detail-info" v-if="px.px">
121 <div class="px-detail-row"> 140 <div class="px-detail-row">
@@ -149,13 +168,17 @@ @@ -149,13 +168,17 @@
149 </div> 168 </div>
150 <div class="px-detail-item"> 169 <div class="px-detail-item">
151 <span class="px-detail-label">总业绩:</span> 170 <span class="px-detail-label">总业绩:</span>
152 - <span class="px-detail-value">{{ (px.projectNumber || 1) * (px.pxjg || 0) }}</span> 171 + <span class="px-detail-value">{{ (px.projectNumber || 1) * (px.pxjg ||
  172 + 0) }}</span>
153 </div> 173 </div>
154 </div> 174 </div>
155 - 175 +
156 <!-- 消费数量输入 --> 176 <!-- 消费数量输入 -->
157 <div class="px-consumption-row"> 177 <div class="px-consumption-row">
158 - <el-input-number v-model="px.projectNumber" :min="1" :max="getRemainingCount(px)" placeholder="消费数量" size="mini" style="width: 120px;" @change="onPxProjectNumberChange(pxIndex, $event)"></el-input-number> 178 + <el-input-number v-model="px.projectNumber" :min="1"
  179 + :max="getRemainingCount(px)" placeholder="消费数量" size="mini"
  180 + style="width: 120px;"
  181 + @change="onPxProjectNumberChange(pxIndex, $event)"></el-input-number>
159 </div> 182 </div>
160 </div> 183 </div>
161 </div> 184 </div>
@@ -164,36 +187,48 @@ @@ -164,36 +187,48 @@
164 <div class="px-staff-section"> 187 <div class="px-staff-section">
165 <div class="px-staff-header"> 188 <div class="px-staff-header">
166 <span class="px-staff-title">健康师业绩</span> 189 <span class="px-staff-title">健康师业绩</span>
167 - <el-button v-if="!dataForm.id" size="mini" type="success" icon="el-icon-plus" @click="addPxJks(pxIndex)">添加健康师</el-button> 190 + <el-button v-if="!dataForm.id" size="mini" type="success" icon="el-icon-plus"
  191 + @click="addPxJks(pxIndex)">添加健康师</el-button>
168 </div> 192 </div>
169 <div class="px-staff-list"> 193 <div class="px-staff-list">
170 - <div v-for="(jks, jksIndex) in px.lqHytkJksyjList" :key="jksIndex" class="px-staff-row"> 194 + <div v-for="(jks, jksIndex) in px.lqHytkJksyjList" :key="jksIndex"
  195 + class="px-staff-row">
171 <div class="px-staff-item"> 196 <div class="px-staff-item">
172 <div class="px-staff-fields"> 197 <div class="px-staff-fields">
173 <div class="px-staff-field"> 198 <div class="px-staff-field">
174 <label>健康师</label> 199 <label>健康师</label>
175 - <el-select v-model="jks.jks" placeholder="选择健康师" clearable filterable size="mini" style="width: 200px;" @change="handleJksChange(pxIndex, jksIndex, jks)">  
176 - <el-option v-for="(item, index) in jksOptions" :key="index" :label="item.fullName" :value="item.id"></el-option> 200 + <el-select v-model="jks.jks" placeholder="选择健康师" clearable
  201 + filterable size="mini" style="width: 200px;"
  202 + @change="handleJksChange(pxIndex, jksIndex, jks)">
  203 + <el-option v-for="(item, index) in jksOptions" :key="index"
  204 + :label="item.fullName" :value="item.id"></el-option>
177 </el-select> 205 </el-select>
178 </div> 206 </div>
179 <div class="px-staff-field"> 207 <div class="px-staff-field">
180 <label>业绩</label> 208 <label>业绩</label>
181 - <el-input v-model="jks.jksyj" placeholder="请输入业绩" size="mini" style="width: 120px;" @input="formatPxStaffNumber(pxIndex, jksIndex, 'jksyj', 'lqHytkJksyjList')"> 209 + <el-input v-model="jks.jksyj" placeholder="请输入业绩" size="mini"
  210 + style="width: 120px;"
  211 + @input="formatPxStaffNumber(pxIndex, jksIndex, 'jksyj', 'lqHytkJksyjList')">
182 <template slot="append">元</template> 212 <template slot="append">元</template>
183 </el-input> 213 </el-input>
184 </div> 214 </div>
185 <div class="px-staff-field" v-show="false"> 215 <div class="px-staff-field" v-show="false">
186 <label>手工费</label> 216 <label>手工费</label>
187 - <el-input v-model="jks.laborCost" placeholder="手工费" size="mini" style="width: 120px;" @input="formatPxStaffNumber(pxIndex, jksIndex, 'laborCost', 'lqHytkJksyjList')"> 217 + <el-input v-model="jks.laborCost" placeholder="手工费" size="mini"
  218 + style="width: 120px;"
  219 + @input="formatPxStaffNumber(pxIndex, jksIndex, 'laborCost', 'lqHytkJksyjList')">
188 <template slot="append">元</template> 220 <template slot="append">元</template>
189 </el-input> 221 </el-input>
190 </div> 222 </div>
191 <div class="px-staff-field"> 223 <div class="px-staff-field">
192 <label>次数</label> 224 <label>次数</label>
193 - <el-input-number v-model="jks.kdpxNumber" :min="1" :max="999" placeholder="次数" size="mini" style="width: 120px;" @change="onJksNumberChange(pxIndex, jksIndex, $event)"></el-input-number> 225 + <el-input-number v-model="jks.kdpxNumber" :min="1" :max="999"
  226 + placeholder="次数" size="mini" style="width: 120px;"
  227 + @change="onJksNumberChange(pxIndex, jksIndex, $event)"></el-input-number>
194 </div> 228 </div>
195 <div class="px-staff-field" v-if="!dataForm.id"> 229 <div class="px-staff-field" v-if="!dataForm.id">
196 - <el-button size="mini" type="danger" icon="el-icon-delete" @click="removePxJks(pxIndex, jksIndex)">删除</el-button> 230 + <el-button size="mini" type="danger" icon="el-icon-delete"
  231 + @click="removePxJks(pxIndex, jksIndex)">删除</el-button>
197 </div> 232 </div>
198 </div> 233 </div>
199 </div> 234 </div>
@@ -202,46 +237,60 @@ @@ -202,46 +237,60 @@
202 </div> 237 </div>
203 238
204 <!-- 科技部老师业绩区域 - 仅当品项类型为科美时显示 --> 239 <!-- 科技部老师业绩区域 - 仅当品项类型为科美时显示 -->
205 - <div class="px-staff-section" v-if="px.qt2 === '科美'" :key="'kjb-' + pxIndex + '-' + px.qt2"> 240 + <div class="px-staff-section" v-if="px.qt2 === '科美'"
  241 + :key="'kjb-' + pxIndex + '-' + px.qt2">
206 <div class="px-staff-header"> 242 <div class="px-staff-header">
207 <span class="px-staff-title">科技部老师业绩</span> 243 <span class="px-staff-title">科技部老师业绩</span>
208 - <el-button v-if="!dataForm.id" size="mini" type="success" icon="el-icon-plus" @click="addPxKjb(pxIndex)">添加科技部老师</el-button> 244 + <el-button v-if="!dataForm.id" size="mini" type="success" icon="el-icon-plus"
  245 + @click="addPxKjb(pxIndex)">添加科技部老师</el-button>
209 </div> 246 </div>
210 <div class="px-staff-list"> 247 <div class="px-staff-list">
211 - <div v-for="(kjb, kjbIndex) in px.lqHytkKjbsyjList" :key="kjbIndex" class="px-staff-row"> 248 + <div v-for="(kjb, kjbIndex) in px.lqHytkKjbsyjList" :key="kjbIndex"
  249 + class="px-staff-row">
212 <div class="px-staff-item"> 250 <div class="px-staff-item">
213 <div class="px-staff-fields"> 251 <div class="px-staff-fields">
214 <div class="px-staff-field"> 252 <div class="px-staff-field">
215 <label>科技部老师</label> 253 <label>科技部老师</label>
216 - <el-select v-model="kjb.kjbls" placeholder="选择科技部老师" clearable filterable size="mini" style="width: 200px;" @change="handleKjbChange(pxIndex, kjbIndex, kjb)">  
217 - <el-option v-for="(item, index) in kjbOptions" :key="index" :label="item.fullName" :value="item.id"></el-option> 254 + <el-select v-model="kjb.kjbls" placeholder="选择科技部老师" clearable
  255 + filterable size="mini" style="width: 200px;"
  256 + @change="handleKjbChange(pxIndex, kjbIndex, kjb)">
  257 + <el-option v-for="(item, index) in kjbOptions" :key="index"
  258 + :label="item.fullName" :value="item.id"></el-option>
218 </el-select> 259 </el-select>
219 </div> 260 </div>
220 <div class="px-staff-field"> 261 <div class="px-staff-field">
221 <label>业绩</label> 262 <label>业绩</label>
222 - <el-input v-model="kjb.kjblsyj" placeholder="请输入业绩" size="mini" style="width: 120px;" @input="formatPxStaffNumber(pxIndex, kjbIndex, 'kjblsyj', 'lqHytkKjbsyjList')"> 263 + <el-input v-model="kjb.kjblsyj" placeholder="请输入业绩" size="mini"
  264 + style="width: 120px;"
  265 + @input="formatPxStaffNumber(pxIndex, kjbIndex, 'kjblsyj', 'lqHytkKjbsyjList')">
223 <template slot="append">元</template> 266 <template slot="append">元</template>
224 </el-input> 267 </el-input>
225 </div> 268 </div>
226 - <div class="px-staff-field" v-show="false" style="justify-content: space-around;padding-bottom: 30rpx;"> 269 + <div class="px-staff-field" v-show="false"
  270 + style="justify-content: space-around;padding-bottom: 30rpx;">
227 <label>手工费</label> 271 <label>手工费</label>
228 - <el-input v-model="kjb.laborCost" placeholder="手工费" size="mini" style="width: 120px;" @input="formatPxStaffNumber(pxIndex, kjbIndex, 'laborCost', 'lqHytkKjbsyjList')"> 272 + <el-input v-model="kjb.laborCost" placeholder="手工费" size="mini"
  273 + style="width: 120px;"
  274 + @input="formatPxStaffNumber(pxIndex, kjbIndex, 'laborCost', 'lqHytkKjbsyjList')">
229 <template slot="append">元</template> 275 <template slot="append">元</template>
230 </el-input> 276 </el-input>
231 </div> 277 </div>
232 <div class="px-staff-field"> 278 <div class="px-staff-field">
233 <label>次数</label> 279 <label>次数</label>
234 - <el-input-number v-model="kjb.hdpxNumber" :min="1" :max="999" placeholder="次数" size="mini" style="width: 120px;" @change="onKjbNumberChange(pxIndex, kjbIndex, $event)"></el-input-number> 280 + <el-input-number v-model="kjb.hdpxNumber" :min="1" :max="999"
  281 + placeholder="次数" size="mini" style="width: 120px;"
  282 + @change="onKjbNumberChange(pxIndex, kjbIndex, $event)"></el-input-number>
235 </div> 283 </div>
236 <div class="px-staff-field" v-if="!dataForm.id"> 284 <div class="px-staff-field" v-if="!dataForm.id">
237 - <el-button size="mini" type="danger" icon="el-icon-delete" @click="removePxKjb(pxIndex, kjbIndex)">删除</el-button> 285 + <el-button size="mini" type="danger" icon="el-icon-delete"
  286 + @click="removePxKjb(pxIndex, kjbIndex)">删除</el-button>
238 </div> 287 </div>
239 </div> 288 </div>
240 </div> 289 </div>
241 </div> 290 </div>
242 </div> 291 </div>
243 </div> 292 </div>
244 - 293 +
245 <!-- 非科美品项提示 --> 294 <!-- 非科美品项提示 -->
246 <div class="px-staff-section" v-if="px.qt2 && px.qt2 !== '科美'"> 295 <div class="px-staff-section" v-if="px.qt2 && px.qt2 !== '科美'">
247 <div class="px-staff-header"> 296 <div class="px-staff-header">
@@ -257,18 +306,19 @@ @@ -257,18 +306,19 @@
257 </el-form-item> 306 </el-form-item>
258 </el-col> 307 </el-col>
259 <el-col :span="24"> 308 <el-col :span="24">
260 - <el-form-item label="备注" prop="bz">  
261 - <el-input v-model="dataForm.bz" placeholder="请输入" show-word-limit :style='{"width":"100%"}' type='textarea' :autosize='{"minRows":4,"maxRows":4}' >  
262 - </el-input>  
263 - </el-form-item>  
264 - </el-col>  
265 - <el-col :span="24">  
266 - <el-form-item label="上传文件" prop="fileUrl">  
267 - <NCC-UploadImg v-model="dataForm.fileUrl" :fileSize="30" sizeUnit="MB" :limit="9" >  
268 - </NCC-UploadImg>  
269 - </el-form-item>  
270 - </el-col>  
271 - </el-form> 309 + <el-form-item label="备注" prop="bz">
  310 + <el-input v-model="dataForm.bz" placeholder="请输入" show-word-limit :style='{ "width": "100%" }'
  311 + type='textarea' :autosize='{ "minRows": 4, "maxRows": 4 }'>
  312 + </el-input>
  313 + </el-form-item>
  314 + </el-col>
  315 + <el-col :span="24">
  316 + <el-form-item label="上传文件" prop="fileUrl">
  317 + <NCC-UploadImg v-model="dataForm.fileUrl" :fileSize="30" sizeUnit="MB" :limit="9">
  318 + </NCC-UploadImg>
  319 + </el-form-item>
  320 + </el-col>
  321 + </el-form>
272 </el-row> 322 </el-row>
273 <span slot="footer" class="dialog-footer"> 323 <span slot="footer" class="dialog-footer">
274 <el-button @click="visible = false">取 消</el-button> 324 <el-button @click="visible = false">取 消</el-button>
@@ -277,291 +327,291 @@ @@ -277,291 +327,291 @@
277 </el-dialog> 327 </el-dialog>
278 </template> 328 </template>
279 <script> 329 <script>
280 - import request from '@/utils/request'  
281 - import { getDictionaryDataSelector } from '@/api/systemData/dictionary'  
282 - import { previewDataInterface } from '@/api/systemData/dataInterface'  
283 - import { getInfo } from '@/api/user'  
284 - export default {  
285 - components: {},  
286 - props: [],  
287 - data() {  
288 - return {  
289 - loading: false,  
290 - visible: false,  
291 - isDetail: false,  
292 - dataForm: {  
293 - id:'',  
294 - id:undefined,  
295 - md:undefined,  
296 - mdbh:undefined,  
297 - mdmc:undefined,  
298 - hy:undefined,  
299 - hymc:undefined,  
300 - hyzh:undefined,  
301 - tkje:undefined,  
302 - sgfy:undefined,  
303 - bz:undefined,  
304 - tkpx:undefined,  
305 - tksj:new Date(),  
306 - tkr:undefined,  
307 - fileUrl:undefined,  
308 - lqHytkJksyjList:[],  
309 - lqHytkKjbsyjList:[],  
310 - lqHytkMxList:[],  
311 - },  
312 - rules: {  
313 - md: [  
314 - { required: true, message: '请选择门店', trigger: 'change' }  
315 - ],  
316 - hy: [  
317 - { required: true, message: '请选择会员', trigger: 'change' }  
318 - ]  
319 - },  
320 - mdOptions : [],  
321 - hyOptions : [],  
322 - pxOptions : [],  
323 - jksOptions:[],  
324 - kjbOptions:[], 330 +import request from '@/utils/request'
  331 +import { getDictionaryDataSelector } from '@/api/systemData/dictionary'
  332 +import { previewDataInterface } from '@/api/systemData/dataInterface'
  333 +import { getInfo } from '@/api/user'
  334 +export default {
  335 + components: {},
  336 + props: [],
  337 + data() {
  338 + return {
  339 + loading: false,
  340 + visible: false,
  341 + isDetail: false,
  342 + dataForm: {
  343 + id: '',
  344 + id: undefined,
  345 + md: undefined,
  346 + mdbh: undefined,
  347 + mdmc: undefined,
  348 + hy: undefined,
  349 + hymc: undefined,
  350 + hyzh: undefined,
  351 + tkje: undefined,
  352 + sgfy: undefined,
  353 + bz: undefined,
  354 + tkpx: undefined,
  355 + tksj: new Date(),
  356 + tkr: undefined,
  357 + fileUrl: undefined,
  358 + lqHytkJksyjList: [],
  359 + lqHytkKjbsyjList: [],
  360 + lqHytkMxList: [],
  361 + },
  362 + rules: {
  363 + md: [
  364 + { required: true, message: '请选择门店', trigger: 'change' }
  365 + ],
  366 + hy: [
  367 + { required: true, message: '请选择会员', trigger: 'change' }
  368 + ]
  369 + },
  370 + mdOptions: [],
  371 + hyOptions: [],
  372 + pxOptions: [],
  373 + jksOptions: [],
  374 + kjbOptions: [],
  375 + }
  376 + },
  377 + computed: {},
  378 + watch: {},
  379 + created() {
  380 + // 门店数据在loadStoreDataAndSetDefault中加载,避免重复
  381 + this.gethyOptions();
  382 + this.getpxOptions();
  383 + },
  384 + mounted() {
  385 + },
  386 + methods: {
  387 + // 门店选择变化处理
  388 + handleMdChange(val) {
  389 + const selectedMd = this.mdOptions.find(item => item.id === val);
  390 + if (selectedMd) {
  391 + this.dataForm.mdbh = selectedMd.mdbh || selectedMd.id;
  392 + this.dataForm.mdmc = selectedMd.fullName;
  393 + console.log('选择门店:', selectedMd);
  394 + } else {
  395 + this.dataForm.mdbh = '';
  396 + this.dataForm.mdmc = '';
325 } 397 }
326 }, 398 },
327 - computed: {},  
328 - watch: {},  
329 - created() {  
330 - // 门店数据在loadStoreDataAndSetDefault中加载,避免重复  
331 - this.gethyOptions();  
332 - this.getpxOptions(); 399 + // 会员选择变化处理
  400 + handleHyChange(val) {
  401 + const selectedHy = this.hyOptions.find(item => item.id === val);
  402 + if (selectedHy) {
  403 + this.dataForm.hyzh = selectedHy.hyzh || selectedHy.id;
  404 + this.dataForm.hymc = selectedHy.fullName;
  405 + console.log('选择会员:', selectedHy);
  406 +
  407 + // 清空已选择的品项列表
  408 + this.dataForm.lqHytkMxList = [];
  409 +
  410 + // 选择会员后,获取该会员的剩余品项
  411 + this.getpxOptions();
  412 + } else {
  413 + this.dataForm.hyzh = '';
  414 + this.dataForm.hymc = '';
  415 + this.pxOptions = []; // 清空品项选项
  416 + this.dataForm.lqHytkMxList = []; // 清空已选择的品项列表
  417 +
  418 + // 重新计算总金额和总手工费
  419 + this.calculateTotalAmount();
  420 + this.calculateTotalLaborCost();
  421 + }
333 }, 422 },
334 - mounted() {  
335 - },  
336 - methods: {  
337 - // 门店选择变化处理  
338 - handleMdChange(val) {  
339 - const selectedMd = this.mdOptions.find(item => item.id === val);  
340 - if (selectedMd) {  
341 - this.dataForm.mdbh = selectedMd.mdbh || selectedMd.id;  
342 - this.dataForm.mdmc = selectedMd.fullName;  
343 - console.log('选择门店:', selectedMd);  
344 - } else {  
345 - this.dataForm.mdbh = '';  
346 - this.dataForm.mdmc = '';  
347 - }  
348 - },  
349 - // 会员选择变化处理  
350 - handleHyChange(val) {  
351 - const selectedHy = this.hyOptions.find(item => item.id === val);  
352 - if (selectedHy) {  
353 - this.dataForm.hyzh = selectedHy.hyzh || selectedHy.id;  
354 - this.dataForm.hymc = selectedHy.fullName;  
355 - console.log('选择会员:', selectedHy);  
356 -  
357 - // 清空已选择的品项列表  
358 - this.dataForm.lqHytkMxList = [];  
359 -  
360 - // 选择会员后,获取该会员的剩余品项  
361 - this.getpxOptions();  
362 - } else {  
363 - this.dataForm.hyzh = '';  
364 - this.dataForm.hymc = '';  
365 - this.pxOptions = []; // 清空品项选项  
366 - this.dataForm.lqHytkMxList = []; // 清空已选择的品项列表  
367 -  
368 - // 重新计算总金额和总手工费  
369 - this.calculateTotalAmount();  
370 - this.calculateTotalLaborCost();  
371 - }  
372 - },  
373 - // 品项选择变化处理  
374 - handlePxChange(index, row) {  
375 - if (row.pxid) {  
376 - const selectedPx = this.pxOptions.find(item => item.pxid === row.pxid);  
377 - if (selectedPx) {  
378 - request({  
379 - url: `/api/Extend/LqXmzl/${selectedPx.id}`,  
380 - method: 'GET',  
381 - }).then((res) => {  
382 - let qt2 = res.data.qt2 || "";  
383 - let sgf = res.data.sgf || 0;  
384 - row.px = selectedPx.id;  
385 - row.pxmc = selectedPx.fullName;  
386 - row.pxjg = selectedPx.ItemPrice || 0;  
387 - row.qt2 = qt2 || "";  
388 - row.yxf = selectedPx.ConsumedCount || 0; // 已消费  
389 - row.zgm = selectedPx.TotalPurchased || 1; // 总购买  
390 - row.ly = selectedPx.sourceType || "购买"; // 来源  
391 - row.projectNumber = 1; // 默认消费数量为1  
392 - row.sgf = sgf;  
393 -  
394 - // 品项切换时,清空所有人员列表  
395 - row.lqHytkJksyjList = []; // 清空健康师列表  
396 - row.lqHytkKjbsyjList = []; // 清空科技部老师列表  
397 -  
398 - console.log('选择品项:', selectedPx.fullName, 'qt2:', selectedPx.qt2, '剩余数量:', selectedPx.RemainingCount, '手工费:', sgf);  
399 -  
400 - // 重新计算总金额和总手工费  
401 - this.calculateTotalAmount();  
402 - this.calculateTotalLaborCost();  
403 - })  
404 - }  
405 - } else {  
406 - // 清空品项时,重置所有相关字段  
407 - row.pxmc = '';  
408 - row.pxjg = 0;  
409 - row.qt2 = '';  
410 - row.yxf = 0;  
411 - row.zgm = 1;  
412 - row.ly = '购买';  
413 - row.projectNumber = 1;  
414 - row.sgf = 0; // 清空手工费  
415 - row.lqHytkJksyjList = []; // 清空健康师列表  
416 - row.lqHytkKjbsyjList = []; // 清空科技部老师列表  
417 -  
418 - // 重新计算总金额和总手工费  
419 - this.calculateTotalAmount();  
420 - this.calculateTotalLaborCost();  
421 - }  
422 - },  
423 - getmdOptions(){  
424 - previewDataInterface('730960205902251269').then(res => {  
425 - this.mdOptions = res.data  
426 - });  
427 - },  
428 - gethyOptions(){  
429 - previewDataInterface('730998109110273285').then(res => {  
430 - this.hyOptions = res.data  
431 - });  
432 - },  
433 - // 获取品项选项(从会员剩余品项API获取)  
434 - async getpxOptions() {  
435 - if (!this.dataForm.hy) {  
436 - console.warn("请先选择会员");  
437 - this.pxOptions = [];  
438 - return; 423 + // 品项选择变化处理
  424 + handlePxChange(index, row) {
  425 + if (row.pxid) {
  426 + const selectedPx = this.pxOptions.find(item => item.pxid === row.pxid);
  427 + if (selectedPx) {
  428 + request({
  429 + url: `/api/Extend/LqXmzl/${selectedPx.id}`,
  430 + method: 'GET',
  431 + }).then((res) => {
  432 + let qt2 = res.data.qt2 || "";
  433 + let sgf = res.data.sgf || 0;
  434 + row.px = selectedPx.id;
  435 + row.pxmc = selectedPx.fullName;
  436 + row.pxjg = selectedPx.ItemPrice || 0;
  437 + row.qt2 = qt2 || "";
  438 + row.yxf = selectedPx.ConsumedCount || 0; // 已消费
  439 + row.zgm = selectedPx.TotalPurchased || 1; // 总购买
  440 + row.ly = selectedPx.sourceType || "购买"; // 来源
  441 + row.projectNumber = 1; // 默认消费数量为1
  442 + row.sgf = sgf;
  443 +
  444 + // 品项切换时,清空所有人员列表
  445 + row.lqHytkJksyjList = []; // 清空健康师列表
  446 + row.lqHytkKjbsyjList = []; // 清空科技部老师列表
  447 +
  448 + console.log('选择品项:', selectedPx.fullName, 'qt2:', selectedPx.qt2, '剩余数量:', selectedPx.RemainingCount, '手工费:', sgf);
  449 +
  450 + // 重新计算总金额和总手工费
  451 + this.calculateTotalAmount();
  452 + this.calculateTotalLaborCost();
  453 + })
439 } 454 }
  455 + } else {
  456 + // 清空品项时,重置所有相关字段
  457 + row.pxmc = '';
  458 + row.pxjg = 0;
  459 + row.qt2 = '';
  460 + row.yxf = 0;
  461 + row.zgm = 1;
  462 + row.ly = '购买';
  463 + row.projectNumber = 1;
  464 + row.sgf = 0; // 清空手工费
  465 + row.lqHytkJksyjList = []; // 清空健康师列表
  466 + row.lqHytkKjbsyjList = []; // 清空科技部老师列表
440 467
441 - try {  
442 - const response = await request({  
443 - url: `/api/Extend/lqkhxx/GetMemberRemainingItems?memberId=${this.dataForm.hy}`,  
444 - method: 'GET',  
445 - }); 468 + // 重新计算总金额和总手工费
  469 + this.calculateTotalAmount();
  470 + this.calculateTotalLaborCost();
  471 + }
  472 + },
  473 + getmdOptions() {
  474 + previewDataInterface('730960205902251269').then(res => {
  475 + this.mdOptions = res.data
  476 + });
  477 + },
  478 + gethyOptions() {
  479 + previewDataInterface('730998109110273285').then(res => {
  480 + this.hyOptions = res.data
  481 + });
  482 + },
  483 + // 获取品项选项(从会员剩余品项API获取)
  484 + async getpxOptions() {
  485 + if (!this.dataForm.hy) {
  486 + console.warn("请先选择会员");
  487 + this.pxOptions = [];
  488 + return;
  489 + }
446 490
447 - if (response.code == 200 && response.data && response.data.RemainingItems) {  
448 - this.pxOptions = response.data.RemainingItems.map(item => ({  
449 - fullName: item.ItemName,  
450 - id: item.ItemId,  
451 - value: item.ItemId,  
452 - label: item.ItemName,  
453 - px: item.ItemId,  
454 - pxmc: item.ItemName,  
455 - pxjg: item.ItemPrice || 0,  
456 - qt2: item.qt2 || "",  
457 - RemainingCount: item.RemainingCount || 0,  
458 - ItemPrice: item.ItemPrice || 0,  
459 - sgf: 0,  
460 - sourceType: item.SourceType || "购买",  
461 - TotalPurchased: item.TotalPurchased || 0,  
462 - ConsumedCount: item.ConsumedCount || 0,  
463 - pxid: item.ItemId+','+item.SourceType  
464 - }));  
465 - console.log('获取会员剩余品项成功:', this.pxOptions);  
466 - } else {  
467 - console.warn("获取会员剩余品项失败,使用默认数据");  
468 - this.pxOptions = [];  
469 - }  
470 - } catch (error) {  
471 - console.error("获取会员剩余品项出错:", error);  
472 - this.pxOptions = [];  
473 - }  
474 - },  
475 - // 获取健康师选项  
476 - getjksOptions() {  
477 - request({  
478 - url: `/api/Extend/user?page=1&pageSize=1000&mdid=${this.dataForm.md}&gw=健康师`,  
479 - method: 'GET',  
480 - }).then((res) => {  
481 - if (res.code == 200 && res.data.list.length > 0) {  
482 - this.jksOptions = res.data.list.map(item => ({  
483 - fullName: item.realName || item.name || item.userName,  
484 - id: item.id,  
485 - value: item.id,  
486 - label: item.realName || item.name || item.userName,  
487 - jks: item.id,  
488 - jksxm: item.realName || item.name || item.userName,  
489 - jkszh: item.mobilePhone || item.account || item.userName  
490 - }));  
491 - } else {  
492 - this.jksOptions = [];  
493 - }  
494 - })  
495 - },  
496 - // 获取科技部老师选项  
497 - async getkjbOptions() {  
498 - await this.getKjbOptionsByOrganizeId();  
499 - },  
500 - // 根据门店ID获取科技部组织ID,再获取科技部老师列表  
501 - async getKjbOptionsByOrganizeId() {  
502 - const userResponse = await request({  
503 - url: `/api/Extend/user?page=1&pageSize=1000&gw=科技老师`, 491 + try {
  492 + const response = await request({
  493 + url: `/api/Extend/lqkhxx/GetMemberRemainingItems?memberId=${this.dataForm.hy}`,
504 method: 'GET', 494 method: 'GET',
505 }); 495 });
506 -  
507 - if (userResponse.code == 200 && userResponse.data && userResponse.data.list.length > 0) {  
508 - this.kjbOptions = userResponse.data.list.map(item => ({ 496 +
  497 + if (response.code == 200 && response.data && response.data.RemainingItems) {
  498 + this.pxOptions = response.data.RemainingItems.map(item => ({
  499 + fullName: item.ItemName,
  500 + id: item.ItemId,
  501 + value: item.ItemId,
  502 + label: item.ItemName,
  503 + px: item.ItemId,
  504 + pxmc: item.ItemName,
  505 + pxjg: item.ItemPrice || 0,
  506 + qt2: item.qt2 || "",
  507 + RemainingCount: item.RemainingCount || 0,
  508 + ItemPrice: item.ItemPrice || 0,
  509 + sgf: 0,
  510 + sourceType: item.SourceType || "购买",
  511 + TotalPurchased: item.TotalPurchased || 0,
  512 + ConsumedCount: item.ConsumedCount || 0,
  513 + pxid: item.ItemId + ',' + item.SourceType
  514 + }));
  515 + console.log('获取会员剩余品项成功:', this.pxOptions);
  516 + } else {
  517 + console.warn("获取会员剩余品项失败,使用默认数据");
  518 + this.pxOptions = [];
  519 + }
  520 + } catch (error) {
  521 + console.error("获取会员剩余品项出错:", error);
  522 + this.pxOptions = [];
  523 + }
  524 + },
  525 + // 获取健康师选项
  526 + getjksOptions() {
  527 + request({
  528 + url: `/api/Extend/user?page=1&pageSize=1000&mdid=${this.dataForm.md}&gw=健康师`,
  529 + method: 'GET',
  530 + }).then((res) => {
  531 + if (res.code == 200 && res.data.list.length > 0) {
  532 + this.jksOptions = res.data.list.map(item => ({
509 fullName: item.realName || item.name || item.userName, 533 fullName: item.realName || item.name || item.userName,
510 id: item.id, 534 id: item.id,
511 value: item.id, 535 value: item.id,
512 label: item.realName || item.name || item.userName, 536 label: item.realName || item.name || item.userName,
513 - kjbls: item.id,  
514 - kjblsxm: item.realName || item.name || item.userName,  
515 - kjblszh: item.mobilePhone || item.account || item.userName 537 + jks: item.id,
  538 + jksxm: item.realName || item.name || item.userName,
  539 + jkszh: item.mobilePhone || item.account || item.userName
516 })); 540 }));
517 - console.log('科技部老师列表:', this.kjbOptions);  
518 } else { 541 } else {
519 - console.warn('获取科技部老师列表失败');  
520 - this.kjbOptions = []; 542 + this.jksOptions = [];
521 } 543 }
522 - },  
523 - // 品项健康师选择  
524 - handleJksChange(pxIndex, jksIndex, row) {  
525 - console.log('品项健康师选择:', row);  
526 - if (row.jks) {  
527 - // 根据选择的健康师ID获取用户信息  
528 - const selectedJks = this.jksOptions.find(item => item.id === row.jks);  
529 - if (selectedJks) {  
530 - // 填充姓名和账号  
531 - row.jksxm = selectedJks.fullName;  
532 - row.jkszh = selectedJks.userName || selectedJks.account || selectedJks.id;  
533 -  
534 - // 获取金三角信息  
535 - this.getJsjInfoByUserId(row.jks, (jsjId, jsjName) => {  
536 - row.jsjName = jsjName;  
537 - row.jsjId = jsjId;  
538 - });  
539 - }  
540 - } else {  
541 - // 清空相关字段  
542 - row.jksxm = '';  
543 - row.jkszh = '';  
544 - row.jsjId = ''; 544 + })
  545 + },
  546 + // 获取科技部老师选项
  547 + async getkjbOptions() {
  548 + await this.getKjbOptionsByOrganizeId();
  549 + },
  550 + // 根据门店ID获取科技部组织ID,再获取科技部老师列表
  551 + async getKjbOptionsByOrganizeId() {
  552 + const userResponse = await request({
  553 + url: `/api/Extend/user?page=1&pageSize=1000&gw=科技老师`,
  554 + method: 'GET',
  555 + });
  556 +
  557 + if (userResponse.code == 200 && userResponse.data && userResponse.data.list.length > 0) {
  558 + this.kjbOptions = userResponse.data.list.map(item => ({
  559 + fullName: item.realName || item.name || item.userName,
  560 + id: item.id,
  561 + value: item.id,
  562 + label: item.realName || item.name || item.userName,
  563 + kjbls: item.id,
  564 + kjblsxm: item.realName || item.name || item.userName,
  565 + kjblszh: item.mobilePhone || item.account || item.userName
  566 + }));
  567 + console.log('科技部老师列表:', this.kjbOptions);
  568 + } else {
  569 + console.warn('获取科技部老师列表失败');
  570 + this.kjbOptions = [];
  571 + }
  572 + },
  573 + // 品项健康师选择
  574 + handleJksChange(pxIndex, jksIndex, row) {
  575 + console.log('品项健康师选择:', row);
  576 + if (row.jks) {
  577 + // 根据选择的健康师ID获取用户信息
  578 + const selectedJks = this.jksOptions.find(item => item.id === row.jks);
  579 + if (selectedJks) {
  580 + // 填充姓名和账号
  581 + row.jksxm = selectedJks.fullName;
  582 + row.jkszh = selectedJks.userName || selectedJks.account || selectedJks.id;
  583 +
  584 + // 获取金三角信息
  585 + this.getJsjInfoByUserId(row.jks, (jsjId, jsjName) => {
  586 + row.jsjName = jsjName;
  587 + row.jsjId = jsjId;
  588 + });
545 } 589 }
546 - },  
547 - // 品项科技部老师选择  
548 - handleKjbChange(pxIndex, kjbIndex, row) {  
549 - console.log('品项科技部老师选择:', row);  
550 - if (row.kjbls) {  
551 - // 根据选择的科技部老师ID获取用户信息  
552 - const selectedKjb = this.kjbOptions.find(item => item.id === row.kjbls);  
553 - if (selectedKjb) {  
554 - // 填充姓名和账号  
555 - row.kjblsxm = selectedKjb.fullName;  
556 - row.kjblszh = selectedKjb.userName || selectedKjb.account || selectedKjb.id;  
557 - }  
558 - } else {  
559 - // 清空相关字段  
560 - row.kjblsxm = '';  
561 - row.kjblszh = ''; 590 + } else {
  591 + // 清空相关字段
  592 + row.jksxm = '';
  593 + row.jkszh = '';
  594 + row.jsjId = '';
  595 + }
  596 + },
  597 + // 品项科技部老师选择
  598 + handleKjbChange(pxIndex, kjbIndex, row) {
  599 + console.log('品项科技部老师选择:', row);
  600 + if (row.kjbls) {
  601 + // 根据选择的科技部老师ID获取用户信息
  602 + const selectedKjb = this.kjbOptions.find(item => item.id === row.kjbls);
  603 + if (selectedKjb) {
  604 + // 填充姓名和账号
  605 + row.kjblsxm = selectedKjb.fullName;
  606 + row.kjblszh = selectedKjb.userName || selectedKjb.account || selectedKjb.id;
562 } 607 }
563 - },  
564 - // 格式化日期方法 608 + } else {
  609 + // 清空相关字段
  610 + row.kjblsxm = '';
  611 + row.kjblszh = '';
  612 + }
  613 + },
  614 + // 格式化日期方法
565 formatDate(date, format) { 615 formatDate(date, format) {
566 if (!date) return ''; 616 if (!date) return '';
567 const d = new Date(date); 617 const d = new Date(date);
@@ -571,7 +621,7 @@ @@ -571,7 +621,7 @@
571 const hours = String(d.getHours()).padStart(2, '0'); 621 const hours = String(d.getHours()).padStart(2, '0');
572 const minutes = String(d.getMinutes()).padStart(2, '0'); 622 const minutes = String(d.getMinutes()).padStart(2, '0');
573 const seconds = String(d.getSeconds()).padStart(2, '0'); 623 const seconds = String(d.getSeconds()).padStart(2, '0');
574 - 624 +
575 return format 625 return format
576 .replace('yyyy', year) 626 .replace('yyyy', year)
577 .replace('MM', month) 627 .replace('MM', month)
@@ -580,629 +630,629 @@ @@ -580,629 +630,629 @@
580 .replace('mm', minutes) 630 .replace('mm', minutes)
581 .replace('ss', seconds); 631 .replace('ss', seconds);
582 }, 632 },
583 - // 根据用户ID获取金三角信息  
584 - getJsjInfoByUserId(userId, callback) {  
585 - let date = new Date(this.dataForm.tksj);  
586 - let formattedDate = this.formatDate(date, 'yyyy-MM-dd HH:mm:ss');  
587 - console.log('formattedDate:', formattedDate);  
588 - request({  
589 - url: `/api/Extend/lqycsdjsj/GetJsjInfoByUserMonth?UserId=${userId}&DateTime=${formattedDate}`,  
590 - method: 'GET',  
591 - }).then((res) => {  
592 - if (res.code === 200 && res.data) {  
593 - // 假设返回的数据结构中有jsj_id字段  
594 - const jsjId = res.data.jsjId;  
595 - const jsjName = res.data.jsjName;  
596 -  
597 - if (callback) {  
598 - callback(jsjId, jsjName);  
599 - }  
600 - console.log('获取金三角信息成功:', res.data);  
601 - } else {  
602 - console.warn('获取金三角信息失败:', res.msg);  
603 - if (callback) {  
604 - callback('');  
605 - } 633 + // 根据用户ID获取金三角信息
  634 + getJsjInfoByUserId(userId, callback) {
  635 + let date = new Date(this.dataForm.tksj);
  636 + let formattedDate = this.formatDate(date, 'yyyy-MM-dd HH:mm:ss');
  637 + console.log('formattedDate:', formattedDate);
  638 + request({
  639 + url: `/api/Extend/lqycsdjsj/GetJsjInfoByUserMonth?UserId=${userId}&DateTime=${formattedDate}`,
  640 + method: 'GET',
  641 + }).then((res) => {
  642 + if (res.code === 200 && res.data) {
  643 + // 假设返回的数据结构中有jsj_id字段
  644 + const jsjId = res.data.jsjId;
  645 + const jsjName = res.data.jsjName;
  646 +
  647 + if (callback) {
  648 + callback(jsjId, jsjName);
606 } 649 }
607 - }).catch((err) => {  
608 - console.error('获取金三角信息出错:', err); 650 + console.log('获取金三角信息成功:', res.data);
  651 + } else {
  652 + console.warn('获取金三角信息失败:', res.msg);
609 if (callback) { 653 if (callback) {
610 callback(''); 654 callback('');
611 } 655 }
612 - });  
613 - },  
614 - // 品项内人员业绩数字格式化  
615 - formatPxStaffNumber(pxIndex, staffIndex, field, listName) {  
616 - const targetList = this.dataForm.lqHytkMxList[pxIndex][listName];  
617 - if (targetList && targetList[staffIndex] && targetList[staffIndex][field] !== undefined) {  
618 - let value = targetList[staffIndex][field].toString().replace(/,/g, '');  
619 -  
620 - if (!/^\d*\.?\d*$/.test(value)) {  
621 - value = value.replace(/[^\d.]/g, '');  
622 - }  
623 -  
624 - targetList[staffIndex][field] = value;  
625 } 656 }
626 - },  
627 - // 获取品项剩余数量  
628 - getRemainingCount(px) {  
629 - if (px.px) {  
630 - const selectedPx = this.pxOptions.find(item => item.id === px.px);  
631 - if (selectedPx) {  
632 - return selectedPx.RemainingCount || 0;  
633 - } 657 + }).catch((err) => {
  658 + console.error('获取金三角信息出错:', err);
  659 + if (callback) {
  660 + callback('');
634 } 661 }
635 - return (px.zgm || 1) - (px.yxf || 0);  
636 - },  
637 - // 消费数量变化处理  
638 - onProjectNumberChange() {  
639 - // 重新计算总金额和总手工费  
640 - this.calculateTotalAmount();  
641 - this.calculateTotalLaborCost();  
642 - },  
643 - // 品项消费数量变化处理(带参数)  
644 - onPxProjectNumberChange(pxIndex, projectNumber) {  
645 - // 更新品项的消费数量  
646 - this.dataForm.lqHytkMxList[pxIndex].projectNumber = projectNumber;  
647 -  
648 - // 获取当前品项的手工费  
649 - const currentPx = this.dataForm.lqHytkMxList[pxIndex];  
650 - const laborCost = currentPx.sgf || 0;  
651 -  
652 - // 更新该品项下所有人员的手工费  
653 - this.updatePxStaffLaborCost(pxIndex, laborCost);  
654 -  
655 - // 重新计算总金额和总手工费  
656 - this.calculateTotalAmount();  
657 - this.calculateTotalLaborCost();  
658 - },  
659 - // 更新品项下所有人员的手工费  
660 - updatePxStaffLaborCost(pxIndex, newLaborCost) {  
661 - const currentPx = this.dataForm.lqHytkMxList[pxIndex];  
662 - console.log('更新品项手工费:', {  
663 - pxIndex,  
664 - newLaborCost,  
665 - pxName: currentPx.pxmc,  
666 - hasJks: currentPx.lqHytkJksyjList && currentPx.lqHytkJksyjList.length > 0,  
667 - hasKjb: currentPx.lqHytkKjbsyjList && currentPx.lqHytkKjbsyjList.length > 0  
668 - });  
669 -  
670 - // 更新健康师的手工费 = 品项手工费 × 健康师次数  
671 - if (currentPx.lqHytkJksyjList && currentPx.lqHytkJksyjList.length > 0) {  
672 - currentPx.lqHytkJksyjList.forEach((jks, index) => {  
673 - const jksLaborCost = newLaborCost * (jks.kdpxNumber || 1);  
674 - console.log(`更新健康师${index}手工费:`, jks.laborCost, '->', jksLaborCost, `(${newLaborCost} × ${jks.kdpxNumber || 1})`);  
675 - // 使用Vue.set确保响应式更新  
676 - this.$set(jks, 'laborCost', jksLaborCost);  
677 - }); 662 + });
  663 + },
  664 + // 品项内人员业绩数字格式化
  665 + formatPxStaffNumber(pxIndex, staffIndex, field, listName) {
  666 + const targetList = this.dataForm.lqHytkMxList[pxIndex][listName];
  667 + if (targetList && targetList[staffIndex] && targetList[staffIndex][field] !== undefined) {
  668 + let value = targetList[staffIndex][field].toString().replace(/,/g, '');
  669 +
  670 + if (!/^\d*\.?\d*$/.test(value)) {
  671 + value = value.replace(/[^\d.]/g, '');
678 } 672 }
679 -  
680 - // 更新科技部老师的手工费 = 品项手工费 × 科技部老师次数  
681 - if (currentPx.lqHytkKjbsyjList && currentPx.lqHytkKjbsyjList.length > 0) {  
682 - currentPx.lqHytkKjbsyjList.forEach((kjb, index) => {  
683 - const kjbLaborCost = newLaborCost * (kjb.hdpxNumber || 1);  
684 - console.log(`更新科技部老师${index}手工费:`, kjb.laborCost, '->', kjbLaborCost, `(${newLaborCost} × ${kjb.hdpxNumber || 1})`);  
685 - // 使用Vue.set确保响应式更新  
686 - this.$set(kjb, 'laborCost', kjbLaborCost);  
687 - }); 673 +
  674 + targetList[staffIndex][field] = value;
  675 + }
  676 + },
  677 + // 获取品项剩余数量
  678 + getRemainingCount(px) {
  679 + if (px.px) {
  680 + const selectedPx = this.pxOptions.find(item => item.id === px.px);
  681 + if (selectedPx) {
  682 + return selectedPx.RemainingCount || 0;
688 } 683 }
689 - },  
690 - // 健康师次数变化处理  
691 - onJksNumberChange(pxIndex, jksIndex, newNumber) {  
692 - const currentPx = this.dataForm.lqHytkMxList[pxIndex];  
693 - const jks = currentPx.lqHytkJksyjList[jksIndex];  
694 -  
695 - // 更新健康师的次数  
696 - this.$set(jks, 'kdpxNumber', newNumber);  
697 -  
698 - // 重新计算该健康师的手工费 = 品项手工费 × 健康师次数  
699 - const pxLaborCost = currentPx.sgf || 0;  
700 - const newJksLaborCost = pxLaborCost * newNumber;  
701 - this.$set(jks, 'laborCost', newJksLaborCost);  
702 -  
703 - // 重新计算总金额和总手工费  
704 - this.calculateTotalAmount();  
705 - this.calculateTotalLaborCost();  
706 -  
707 - console.log('健康师次数变化:', {  
708 - pxIndex,  
709 - jksIndex,  
710 - newNumber,  
711 - jksName: jks.jksxm,  
712 - pxLaborCost,  
713 - newJksLaborCost,  
714 - formula: `${pxLaborCost} × ${newNumber} = ${newJksLaborCost}`  
715 - });  
716 - },  
717 - // 科技部老师次数变化处理  
718 - onKjbNumberChange(pxIndex, kjbIndex, newNumber) {  
719 - const currentPx = this.dataForm.lqHytkMxList[pxIndex];  
720 - const kjb = currentPx.lqHytkKjbsyjList[kjbIndex];  
721 -  
722 - // 更新科技部老师的次数  
723 - this.$set(kjb, 'hdpxNumber', newNumber);  
724 -  
725 - // 重新计算该科技部老师的手工费 = 品项手工费 × 科技部老师次数  
726 - const pxLaborCost = currentPx.sgf || 0;  
727 - const newKjbLaborCost = pxLaborCost * newNumber;  
728 - this.$set(kjb, 'laborCost', newKjbLaborCost);  
729 -  
730 - // 重新计算总金额和总手工费  
731 - this.calculateTotalAmount();  
732 - this.calculateTotalLaborCost();  
733 -  
734 - console.log('科技部老师次数变化:', {  
735 - pxIndex,  
736 - kjbIndex,  
737 - newNumber,  
738 - kjbName: kjb.kjblsxm,  
739 - pxLaborCost,  
740 - newKjbLaborCost,  
741 - formula: `${pxLaborCost} × ${newNumber} = ${newKjbLaborCost}` 684 + }
  685 + return (px.zgm || 1) - (px.yxf || 0);
  686 + },
  687 + // 消费数量变化处理
  688 + onProjectNumberChange() {
  689 + // 重新计算总金额和总手工费
  690 + this.calculateTotalAmount();
  691 + this.calculateTotalLaborCost();
  692 + },
  693 + // 品项消费数量变化处理(带参数)
  694 + onPxProjectNumberChange(pxIndex, projectNumber) {
  695 + // 更新品项的消费数量
  696 + this.dataForm.lqHytkMxList[pxIndex].projectNumber = projectNumber;
  697 +
  698 + // 获取当前品项的手工费
  699 + const currentPx = this.dataForm.lqHytkMxList[pxIndex];
  700 + const laborCost = currentPx.sgf || 0;
  701 +
  702 + // 更新该品项下所有人员的手工费
  703 + this.updatePxStaffLaborCost(pxIndex, laborCost);
  704 +
  705 + // 重新计算总金额和总手工费
  706 + this.calculateTotalAmount();
  707 + this.calculateTotalLaborCost();
  708 + },
  709 + // 更新品项下所有人员的手工费
  710 + updatePxStaffLaborCost(pxIndex, newLaborCost) {
  711 + const currentPx = this.dataForm.lqHytkMxList[pxIndex];
  712 + console.log('更新品项手工费:', {
  713 + pxIndex,
  714 + newLaborCost,
  715 + pxName: currentPx.pxmc,
  716 + hasJks: currentPx.lqHytkJksyjList && currentPx.lqHytkJksyjList.length > 0,
  717 + hasKjb: currentPx.lqHytkKjbsyjList && currentPx.lqHytkKjbsyjList.length > 0
  718 + });
  719 +
  720 + // 更新健康师的手工费 = 品项手工费 × 健康师次数
  721 + if (currentPx.lqHytkJksyjList && currentPx.lqHytkJksyjList.length > 0) {
  722 + currentPx.lqHytkJksyjList.forEach((jks, index) => {
  723 + const jksLaborCost = newLaborCost * (jks.kdpxNumber || 1);
  724 + console.log(`更新健康师${index}手工费:`, jks.laborCost, '->', jksLaborCost, `(${newLaborCost} × ${jks.kdpxNumber || 1})`);
  725 + // 使用Vue.set确保响应式更新
  726 + this.$set(jks, 'laborCost', jksLaborCost);
742 }); 727 });
743 - },  
744 - // 计算总退款金额  
745 - calculateTotalAmount() {  
746 - let totalAmount = 0;  
747 - this.dataForm.lqHytkMxList.forEach(px => {  
748 - if (px.px && px.pxjg && px.projectNumber) {  
749 - totalAmount += parseFloat(px.pxjg) * parseInt(px.projectNumber);  
750 - } 728 + }
  729 +
  730 + // 更新科技部老师的手工费 = 品项手工费 × 科技部老师次数
  731 + if (currentPx.lqHytkKjbsyjList && currentPx.lqHytkKjbsyjList.length > 0) {
  732 + currentPx.lqHytkKjbsyjList.forEach((kjb, index) => {
  733 + const kjbLaborCost = newLaborCost * (kjb.hdpxNumber || 1);
  734 + console.log(`更新科技部老师${index}手工费:`, kjb.laborCost, '->', kjbLaborCost, `(${newLaborCost} × ${kjb.hdpxNumber || 1})`);
  735 + // 使用Vue.set确保响应式更新
  736 + this.$set(kjb, 'laborCost', kjbLaborCost);
751 }); 737 });
752 - this.dataForm.tkje = totalAmount.toFixed(2);  
753 - },  
754 - // 计算总手工费  
755 - calculateTotalLaborCost() {  
756 - let totalLaborCost = 0;  
757 - this.dataForm.lqHytkMxList.forEach(px => {  
758 - // 只计算品项的手工费 = 品项单次手工费 × 品项消费次数  
759 - if (px.sgf && px.projectNumber) {  
760 - totalLaborCost += parseFloat(px.sgf) * parseInt(px.projectNumber); 738 + }
  739 + },
  740 + // 健康师次数变化处理
  741 + onJksNumberChange(pxIndex, jksIndex, newNumber) {
  742 + const currentPx = this.dataForm.lqHytkMxList[pxIndex];
  743 + const jks = currentPx.lqHytkJksyjList[jksIndex];
  744 +
  745 + // 更新健康师的次数
  746 + this.$set(jks, 'kdpxNumber', newNumber);
  747 +
  748 + // 重新计算该健康师的手工费 = 品项手工费 × 健康师次数
  749 + const pxLaborCost = currentPx.sgf || 0;
  750 + const newJksLaborCost = pxLaborCost * newNumber;
  751 + this.$set(jks, 'laborCost', newJksLaborCost);
  752 +
  753 + // 重新计算总金额和总手工费
  754 + this.calculateTotalAmount();
  755 + this.calculateTotalLaborCost();
  756 +
  757 + console.log('健康师次数变化:', {
  758 + pxIndex,
  759 + jksIndex,
  760 + newNumber,
  761 + jksName: jks.jksxm,
  762 + pxLaborCost,
  763 + newJksLaborCost,
  764 + formula: `${pxLaborCost} × ${newNumber} = ${newJksLaborCost}`
  765 + });
  766 + },
  767 + // 科技部老师次数变化处理
  768 + onKjbNumberChange(pxIndex, kjbIndex, newNumber) {
  769 + const currentPx = this.dataForm.lqHytkMxList[pxIndex];
  770 + const kjb = currentPx.lqHytkKjbsyjList[kjbIndex];
  771 +
  772 + // 更新科技部老师的次数
  773 + this.$set(kjb, 'hdpxNumber', newNumber);
  774 +
  775 + // 重新计算该科技部老师的手工费 = 品项手工费 × 科技部老师次数
  776 + const pxLaborCost = currentPx.sgf || 0;
  777 + const newKjbLaborCost = pxLaborCost * newNumber;
  778 + this.$set(kjb, 'laborCost', newKjbLaborCost);
  779 +
  780 + // 重新计算总金额和总手工费
  781 + this.calculateTotalAmount();
  782 + this.calculateTotalLaborCost();
  783 +
  784 + console.log('科技部老师次数变化:', {
  785 + pxIndex,
  786 + kjbIndex,
  787 + newNumber,
  788 + kjbName: kjb.kjblsxm,
  789 + pxLaborCost,
  790 + newKjbLaborCost,
  791 + formula: `${pxLaborCost} × ${newNumber} = ${newKjbLaborCost}`
  792 + });
  793 + },
  794 + // 计算总退款金额
  795 + calculateTotalAmount() {
  796 + let totalAmount = 0;
  797 + this.dataForm.lqHytkMxList.forEach(px => {
  798 + if (px.px && px.pxjg && px.projectNumber) {
  799 + totalAmount += parseFloat(px.pxjg) * parseInt(px.projectNumber);
  800 + }
  801 + });
  802 + this.dataForm.tkje = totalAmount.toFixed(2);
  803 + },
  804 + // 计算总手工费
  805 + calculateTotalLaborCost() {
  806 + let totalLaborCost = 0;
  807 + this.dataForm.lqHytkMxList.forEach(px => {
  808 + // 只计算品项的手工费 = 品项单次手工费 × 品项消费次数
  809 + if (px.sgf && px.projectNumber) {
  810 + totalLaborCost += parseFloat(px.sgf) * parseInt(px.projectNumber);
  811 + }
  812 + });
  813 + this.dataForm.sgfy = totalLaborCost.toFixed(2);
  814 + console.log('计算总手工费(仅品项):', totalLaborCost, '各品项手工费:', this.dataForm.lqHytkMxList.map(px => ({
  815 + name: px.pxmc,
  816 + sgf: px.sgf,
  817 + projectNumber: px.projectNumber,
  818 + total: parseFloat(px.sgf || 0) * parseInt(px.projectNumber || 0)
  819 + })));
  820 + },
  821 + goBack() {
  822 + this.$emit('refresh')
  823 + },
  824 + init(id, isDetail) {
  825 + this.dataForm.id = id || 0;
  826 + this.visible = true;
  827 + this.isDetail = isDetail || false;
  828 + this.$nextTick(() => {
  829 + this.$refs['elForm'].resetFields();
  830 + if (this.dataForm.id) {
  831 + request({
  832 + url: '/api/Extend/LqHytkHytk/' + this.dataForm.id,
  833 + method: 'get'
  834 + }).then(res => {
  835 + this.dataForm = res.data;
  836 + this.dataForm.fileUrl = this.dataForm.fileUrl ? JSON.parse(this.dataForm.fileUrl) : [];
  837 + })
  838 + } else {
  839 + // 新建时自动设置当前用户门店
  840 + this.loadStoreDataAndSetDefault();
  841 + // 加载健康师和科技部老师选项
  842 + this.getjksOptions();
  843 + this.getkjbOptions();
  844 + // 初始化时计算总金额和总手工费
  845 + this.calculateTotalAmount();
  846 + this.calculateTotalLaborCost();
  847 + }
  848 + })
  849 + },
  850 + dataFormSubmit() {
  851 +
  852 + this.$refs['elForm'].validate((valid) => {
  853 + if (valid) {
  854 + // 验证品项数据
  855 + if (!this.validatePxList()) {
  856 + return;
761 } 857 }
762 - });  
763 - this.dataForm.sgfy = totalLaborCost.toFixed(2);  
764 - console.log('计算总手工费(仅品项):', totalLaborCost, '各品项手工费:', this.dataForm.lqHytkMxList.map(px => ({  
765 - name: px.pxmc,  
766 - sgf: px.sgf,  
767 - projectNumber: px.projectNumber,  
768 - total: parseFloat(px.sgf || 0) * parseInt(px.projectNumber || 0)  
769 - })));  
770 - },  
771 - goBack() {  
772 - this.$emit('refresh')  
773 - },  
774 - init(id, isDetail) {  
775 - this.dataForm.id = id || 0;  
776 - this.visible = true;  
777 - this.isDetail = isDetail || false;  
778 - this.$nextTick(() => {  
779 - this.$refs['elForm'].resetFields();  
780 - if (this.dataForm.id) { 858 +
  859 + // 处理提交格式
  860 + this.processFormData();
  861 + console.log(this.dataForm)
  862 + // return
  863 +
  864 + this.dataForm.fileUrl = JSON.stringify(this.dataForm.fileUrl);
  865 + if (!this.dataForm.id) {
781 request({ 866 request({
782 - url: '/api/Extend/LqHytkHytk/' + this.dataForm.id,  
783 - method: 'get'  
784 - }).then(res =>{  
785 - this.dataForm = res.data;  
786 - this.dataForm.fileUrl = this.dataForm.fileUrl?JSON.parse(this.dataForm.fileUrl):[]; 867 + url: `/api/Extend/LqHytkHytk`,
  868 + method: 'post',
  869 + data: this.dataForm,
  870 + }).then((res) => {
  871 + this.$message({
  872 + message: res.msg,
  873 + type: 'success',
  874 + duration: 1000,
  875 + onClose: () => {
  876 + this.visible = false,
  877 + this.$emit('refresh', true)
  878 + }
  879 + })
787 }) 880 })
788 } else { 881 } else {
789 - // 新建时自动设置当前用户门店  
790 - this.loadStoreDataAndSetDefault();  
791 - // 加载健康师和科技部老师选项  
792 - this.getjksOptions();  
793 - this.getkjbOptions();  
794 - // 初始化时计算总金额和总手工费  
795 - this.calculateTotalAmount();  
796 - this.calculateTotalLaborCost(); 882 + request({
  883 + url: '/api/Extend/LqHytkHytk/' + this.dataForm.id,
  884 + method: 'PUT',
  885 + data: this.dataForm
  886 + }).then((res) => {
  887 + this.$message({
  888 + message: res.msg,
  889 + type: 'success',
  890 + duration: 1000,
  891 + onClose: () => {
  892 + this.visible = false
  893 + this.$emit('refresh', true)
  894 + }
  895 + })
  896 + })
797 } 897 }
798 - })  
799 - },  
800 - dataFormSubmit() {  
801 -  
802 - this.$refs['elForm'].validate((valid) => {  
803 - if (valid) {  
804 - // 验证品项数据  
805 - if (!this.validatePxList()) {  
806 - return;  
807 - } 898 + }
  899 + })
  900 + },
  901 + // 品项相关方法
  902 + addHandleLqXhPxmxEntityList() {
  903 + let item = {
  904 + id: undefined,
  905 + glkdbh: undefined,
  906 + px: undefined,
  907 + pxmc: undefined,
  908 + pxjg: undefined,
  909 + xfzs: undefined,
  910 + yxf: 0, // 已消费
  911 + zgm: 1, // 总购买
  912 + ly: '购买', // 来源
  913 + projectNumber: 1, // 消费数量
  914 + qt2: undefined, // 品项类型
  915 + lqHytkJksyjList: [], // 健康师业绩列表
  916 + lqHytkKjbsyjList: [], // 科技部老师业绩列表
  917 + }
  918 + this.dataForm.lqHytkMxList.push(item);
  919 + // 重新计算总金额和总手工费
  920 + this.calculateTotalAmount();
  921 + this.calculateTotalLaborCost();
  922 + },
  923 + handleDelLqXhPxmxEntityList(index) {
  924 + this.dataForm.lqHytkMxList.splice(index, 1);
  925 + // 重新计算总金额和总手工费
  926 + this.calculateTotalAmount();
  927 + this.calculateTotalLaborCost();
  928 + },
  929 + validatePxList() {
  930 + const pxList = this.dataForm.lqHytkMxList;
808 931
809 - // 处理提交格式  
810 - this.processFormData();  
811 - console.log(this.dataForm)  
812 - // return  
813 -  
814 - this.dataForm.fileUrl = JSON.stringify(this.dataForm.fileUrl);  
815 - if (!this.dataForm.id) {  
816 - request({  
817 - url: `/api/Extend/LqHytkHytk`,  
818 - method: 'post',  
819 - data: this.dataForm,  
820 - }).then((res) => {  
821 - this.$message({  
822 - message: res.msg,  
823 - type: 'success',  
824 - duration: 1000,  
825 - onClose: () => {  
826 - this.visible = false,  
827 - this.$emit('refresh', true)  
828 - }  
829 - })  
830 - })  
831 - } else {  
832 - request({  
833 - url: '/api/Extend/LqHytkHytk/' + this.dataForm.id,  
834 - method: 'PUT',  
835 - data: this.dataForm  
836 - }).then((res) => {  
837 - this.$message({  
838 - message: res.msg,  
839 - type: 'success',  
840 - duration: 1000,  
841 - onClose: () => {  
842 - this.visible = false  
843 - this.$emit('refresh', true)  
844 - }  
845 - })  
846 - })  
847 - }  
848 - }  
849 - })  
850 - },  
851 - // 品项相关方法  
852 - addHandleLqXhPxmxEntityList() {  
853 - let item = {  
854 - id: undefined,  
855 - glkdbh: undefined,  
856 - px: undefined,  
857 - pxmc: undefined,  
858 - pxjg: undefined,  
859 - xfzs: undefined,  
860 - yxf: 0, // 已消费  
861 - zgm: 1, // 总购买  
862 - ly: '购买', // 来源  
863 - projectNumber: 1, // 消费数量  
864 - qt2: undefined, // 品项类型  
865 - lqHytkJksyjList: [], // 健康师业绩列表  
866 - lqHytkKjbsyjList: [], // 科技部老师业绩列表 932 + // 1. 验证是否有品项
  933 + if (!pxList || pxList.length === 0) {
  934 + this.$message.error('请至少添加一个品项');
  935 + return false;
  936 + }
  937 +
  938 + // 2. 验证每个品项的信息
  939 + for (let i = 0; i < pxList.length; i++) {
  940 + const px = pxList[i];
  941 +
  942 + // 验证品项基本信息
  943 + if (!px.px || !px.pxmc) {
  944 + this.$message.error(`第${i + 1}个品项信息不完整,请重新选择`);
  945 + return false;
867 } 946 }
868 - this.dataForm.lqHytkMxList.push(item);  
869 - // 重新计算总金额和总手工费  
870 - this.calculateTotalAmount();  
871 - this.calculateTotalLaborCost();  
872 - },  
873 - handleDelLqXhPxmxEntityList(index) {  
874 - this.dataForm.lqHytkMxList.splice(index, 1);  
875 - // 重新计算总金额和总手工费  
876 - this.calculateTotalAmount();  
877 - this.calculateTotalLaborCost();  
878 - },  
879 - validatePxList(){  
880 - const pxList = this.dataForm.lqHytkMxList;  
881 -  
882 - // 1. 验证是否有品项  
883 - if (!pxList || pxList.length === 0) {  
884 - this.$message.error('请至少添加一个品项'); 947 + if (!px.pxjg || parseFloat(px.pxjg) <= 0) {
  948 + this.$message.error(`第${i + 1}个品项的价格必须大于0`);
885 return false; 949 return false;
886 } 950 }
887 -  
888 - // 2. 验证每个品项的信息  
889 - for (let i = 0; i < pxList.length; i++) {  
890 - const px = pxList[i];  
891 -  
892 - // 验证品项基本信息  
893 - if (!px.px || !px.pxmc) {  
894 - this.$message.error(`第${i + 1}个品项信息不完整,请重新选择`); 951 +
  952 + // 验证退卡次数不能超过剩余次数
  953 + if (px.RemainingCount && px.projectNumber > px.RemainingCount) {
  954 + this.$message.error(`第${i + 1}个品项的退卡次数(${px.projectNumber})不能超过剩余次数(${px.RemainingCount})`);
  955 + return false;
  956 + }
  957 +
  958 + // 验证健康师
  959 + if (!px.lqHytkJksyjList || px.lqHytkJksyjList.length === 0) {
  960 + this.$message.error(`第${i + 1}个品项必须至少选择一个健康师`);
  961 + return false;
  962 + }
  963 +
  964 + // 计算健康师业绩总和
  965 + let jksTotalYj = 0;
  966 + let jksTotalLaborCost = 0;
  967 + let jksTotalNumber = 0;
  968 +
  969 + for (let j = 0; j < px.lqHytkJksyjList.length; j++) {
  970 + const jks = px.lqHytkJksyjList[j];
  971 +
  972 + // 验证健康师是否选择
  973 + if (!jks.jks || !jks.jksxm) {
  974 + this.$message.error(`第${i + 1}个品项的第${j + 1}个健康师必须选择`);
895 return false; 975 return false;
896 } 976 }
897 - if (!px.pxjg || parseFloat(px.pxjg) <= 0) {  
898 - this.$message.error(`第${i + 1}个品项的价格必须大于0`); 977 +
  978 + // 验证健康师业绩必须填写
  979 + if (!jks.jksyj || jks.jksyj.trim() === "") {
  980 + this.$message.error(`第${i + 1}个品项的第${j + 1}个健康师业绩必须填写`);
899 return false; 981 return false;
900 } 982 }
901 -  
902 - // 验证退卡次数不能超过剩余次数  
903 - if (px.RemainingCount && px.projectNumber > px.RemainingCount) {  
904 - this.$message.error(`第${i + 1}个品项的退卡次数(${px.projectNumber})不能超过剩余次数(${px.RemainingCount})`); 983 +
  984 + // 验证业绩为数字
  985 + const yj = parseFloat(jks.jksyj);
  986 + if (isNaN(yj) || yj < 0) {
  987 + this.$message.error(`第${i + 1}个品项的第${j + 1}个健康师业绩必须为有效数字`);
905 return false; 988 return false;
906 } 989 }
907 -  
908 - // 验证健康师  
909 - if (!px.lqHytkJksyjList || px.lqHytkJksyjList.length === 0) {  
910 - this.$message.error(`第${i + 1}个品项必须至少选择一个健康师`); 990 +
  991 + jksTotalYj += yj;
  992 + jksTotalLaborCost += parseFloat(jks.laborCost) || 0;
  993 + jksTotalNumber += parseInt(jks.kdpxNumber) || 0;
  994 + }
  995 +
  996 + // 验证健康师业绩总和等于品项金额
  997 + const pxTotalAmount = px.pxjg * px.projectNumber;
  998 + if (Math.abs(jksTotalYj - pxTotalAmount) > 0.01) {
  999 + this.$message.error(`第${i + 1}个品项的健康师业绩总和(${jksTotalYj.toFixed(2)})必须等于品项金额(${pxTotalAmount.toFixed(2)})`);
  1000 + return false;
  1001 + }
  1002 +
  1003 + // 验证健康师手工费总和等于品项手工费
  1004 + const pxTotalLaborCost = (px.sgf || 0) * px.projectNumber;
  1005 + if (Math.abs(jksTotalLaborCost - pxTotalLaborCost) > 0.01) {
  1006 + this.$message.error(`第${i + 1}个品项的健康师手工费总和(${jksTotalLaborCost.toFixed(2)})必须等于品项手工费(${pxTotalLaborCost.toFixed(2)})`);
  1007 + return false;
  1008 + }
  1009 +
  1010 + // 验证健康师次数总和等于品项次数
  1011 + if (jksTotalNumber !== px.projectNumber) {
  1012 + this.$message.error(`第${i + 1}个品项的健康师次数总和(${jksTotalNumber})必须等于品项次数(${px.projectNumber})`);
  1013 + return false;
  1014 + }
  1015 +
  1016 + // 如果是科美品项,验证科技部老师
  1017 + if (px.qt2 === '科美') {
  1018 + if (!px.lqHytkKjbsyjList || px.lqHytkKjbsyjList.length === 0) {
  1019 + this.$message.error(`第${i + 1}个品项是科美品项,必须至少选择一个科技部老师`);
911 return false; 1020 return false;
912 } 1021 }
913 -  
914 - // 计算健康师业绩总和  
915 - let jksTotalYj = 0;  
916 - let jksTotalLaborCost = 0;  
917 - let jksTotalNumber = 0;  
918 -  
919 - for (let j = 0; j < px.lqHytkJksyjList.length; j++) {  
920 - const jks = px.lqHytkJksyjList[j];  
921 -  
922 - // 验证健康师是否选择  
923 - if (!jks.jks || !jks.jksxm) {  
924 - this.$message.error(`第${i + 1}个品项的第${j + 1}个健康师必须选择`); 1022 +
  1023 + // 计算科技部老师业绩总和
  1024 + let kjbTotalYj = 0;
  1025 + let kjbTotalLaborCost = 0;
  1026 + let kjbTotalNumber = 0;
  1027 +
  1028 + for (let k = 0; k < px.lqHytkKjbsyjList.length; k++) {
  1029 + const kjb = px.lqHytkKjbsyjList[k];
  1030 +
  1031 + // 验证科技部老师是否选择
  1032 + if (!kjb.kjbls || !kjb.kjblsxm) {
  1033 + this.$message.error(`第${i + 1}个品项的第${k + 1}个科技部老师必须选择`);
925 return false; 1034 return false;
926 } 1035 }
927 -  
928 - // 验证健康师业绩必须填写  
929 - if (!jks.jksyj || jks.jksyj.trim() === "") {  
930 - this.$message.error(`第${i + 1}个品项的第${j + 1}个健康师业绩必须填写`); 1036 +
  1037 + // 验证科技部老师业绩必须填写
  1038 + if (!kjb.kjblsyj || kjb.kjblsyj.trim() === "") {
  1039 + this.$message.error(`第${i + 1}个品项的第${k + 1}个科技部老师业绩必须填写`);
931 return false; 1040 return false;
932 } 1041 }
933 - 1042 +
934 // 验证业绩为数字 1043 // 验证业绩为数字
935 - const yj = parseFloat(jks.jksyj); 1044 + const yj = parseFloat(kjb.kjblsyj);
936 if (isNaN(yj) || yj < 0) { 1045 if (isNaN(yj) || yj < 0) {
937 - this.$message.error(`第${i + 1}个品项的第${j + 1}个健康师业绩必须为有效数字`); 1046 + this.$message.error(`第${i + 1}个品项的第${k + 1}个科技部老师业绩必须为有效数字`);
938 return false; 1047 return false;
939 } 1048 }
940 -  
941 - jksTotalYj += yj;  
942 - jksTotalLaborCost += parseFloat(jks.laborCost) || 0;  
943 - jksTotalNumber += parseInt(jks.kdpxNumber) || 0; 1049 +
  1050 + kjbTotalYj += yj;
  1051 + kjbTotalLaborCost += parseFloat(kjb.laborCost) || 0;
  1052 + kjbTotalNumber += parseInt(kjb.hdpxNumber) || 0;
944 } 1053 }
945 -  
946 - // 验证健康师业绩总和等于品项金额  
947 - const pxTotalAmount = px.pxjg * px.projectNumber;  
948 - if (Math.abs(jksTotalYj - pxTotalAmount) > 0.01) {  
949 - this.$message.error(`第${i + 1}个品项的健康师业绩总和(${jksTotalYj.toFixed(2)})必须等于品项金额(${pxTotalAmount.toFixed(2)})`); 1054 +
  1055 + // 验证科技部老师业绩总和等于品项金额
  1056 + if (Math.abs(kjbTotalYj - pxTotalAmount) > 0.01) {
  1057 + this.$message.error(`第${i + 1}个品项的科技部老师业绩总和(${kjbTotalYj.toFixed(2)})必须等于品项金额(${pxTotalAmount.toFixed(2)})`);
950 return false; 1058 return false;
951 } 1059 }
952 -  
953 - // 验证健康师手工费总和等于品项手工费  
954 - const pxTotalLaborCost = (px.sgf || 0) * px.projectNumber;  
955 - if (Math.abs(jksTotalLaborCost - pxTotalLaborCost) > 0.01) {  
956 - this.$message.error(`第${i + 1}个品项的健康师手工费总和(${jksTotalLaborCost.toFixed(2)})必须等于品项手工费(${pxTotalLaborCost.toFixed(2)})`); 1060 +
  1061 + // 验证科技部老师手工费总和等于品项手工费
  1062 + if (Math.abs(kjbTotalLaborCost - pxTotalLaborCost) > 0.01) {
  1063 + this.$message.error(`第${i + 1}个品项的科技部老师手工费总和(${kjbTotalLaborCost.toFixed(2)})必须等于品项手工费(${pxTotalLaborCost.toFixed(2)})`);
957 return false; 1064 return false;
958 } 1065 }
959 -  
960 - // 验证健康师次数总和等于品项次数  
961 - if (jksTotalNumber !== px.projectNumber) {  
962 - this.$message.error(`第${i + 1}个品项的健康师次数总和(${jksTotalNumber})必须等于品项次数(${px.projectNumber})`); 1066 +
  1067 + // 验证科技部老师次数总和等于品项次数
  1068 + if (kjbTotalNumber !== px.projectNumber) {
  1069 + this.$message.error(`第${i + 1}个品项的科技部老师次数总和(${kjbTotalNumber})必须等于品项次数(${px.projectNumber})`);
963 return false; 1070 return false;
964 } 1071 }
965 -  
966 - // 如果是科美品项,验证科技部老师  
967 - if (px.qt2 === '科美') {  
968 - if (!px.lqHytkKjbsyjList || px.lqHytkKjbsyjList.length === 0) {  
969 - this.$message.error(`第${i + 1}个品项是科美品项,必须至少选择一个科技部老师`);  
970 - return false;  
971 - }  
972 -  
973 - // 计算科技部老师业绩总和  
974 - let kjbTotalYj = 0;  
975 - let kjbTotalLaborCost = 0;  
976 - let kjbTotalNumber = 0;  
977 -  
978 - for (let k = 0; k < px.lqHytkKjbsyjList.length; k++) {  
979 - const kjb = px.lqHytkKjbsyjList[k];  
980 -  
981 - // 验证科技部老师是否选择  
982 - if (!kjb.kjbls || !kjb.kjblsxm) {  
983 - this.$message.error(`第${i + 1}个品项的第${k + 1}个科技部老师必须选择`);  
984 - return false;  
985 - }  
986 -  
987 - // 验证科技部老师业绩必须填写  
988 - if (!kjb.kjblsyj || kjb.kjblsyj.trim() === "") {  
989 - this.$message.error(`第${i + 1}个品项的第${k + 1}个科技部老师业绩必须填写`);  
990 - return false;  
991 - }  
992 -  
993 - // 验证业绩为数字  
994 - const yj = parseFloat(kjb.kjblsyj);  
995 - if (isNaN(yj) || yj < 0) {  
996 - this.$message.error(`第${i + 1}个品项的第${k + 1}个科技部老师业绩必须为有效数字`);  
997 - return false;  
998 - }  
999 -  
1000 - kjbTotalYj += yj;  
1001 - kjbTotalLaborCost += parseFloat(kjb.laborCost) || 0;  
1002 - kjbTotalNumber += parseInt(kjb.hdpxNumber) || 0;  
1003 - }  
1004 -  
1005 - // 验证科技部老师业绩总和等于品项金额  
1006 - if (Math.abs(kjbTotalYj - pxTotalAmount) > 0.01) {  
1007 - this.$message.error(`第${i + 1}个品项的科技部老师业绩总和(${kjbTotalYj.toFixed(2)})必须等于品项金额(${pxTotalAmount.toFixed(2)})`);  
1008 - return false;  
1009 - }  
1010 -  
1011 - // 验证科技部老师手工费总和等于品项手工费  
1012 - if (Math.abs(kjbTotalLaborCost - pxTotalLaborCost) > 0.01) {  
1013 - this.$message.error(`第${i + 1}个品项的科技部老师手工费总和(${kjbTotalLaborCost.toFixed(2)})必须等于品项手工费(${pxTotalLaborCost.toFixed(2)})`);  
1014 - return false;  
1015 - }  
1016 -  
1017 - // 验证科技部老师次数总和等于品项次数  
1018 - if (kjbTotalNumber !== px.projectNumber) {  
1019 - this.$message.error(`第${i + 1}个品项的科技部老师次数总和(${kjbTotalNumber})必须等于品项次数(${px.projectNumber})`);  
1020 - return false;  
1021 - }  
1022 - }  
1023 - }  
1024 -  
1025 - return true;  
1026 - },  
1027 - // 处理表单数据  
1028 - processFormData() {  
1029 - // 检查是否有科美品项  
1030 - const hasKemei = this.dataForm.lqHytkMxList.some(px => px.qt2 === '科美');  
1031 -  
1032 - // 设置是否有科技部  
1033 - this.dataForm.sfykjb = hasKemei ? "是" : "否";  
1034 -  
1035 - // 处理品项列表,转换为指定格式  
1036 - this.dataForm.lqHytkMxList = this.dataForm.lqHytkMxList.map(px => {  
1037 - // 计算退卡金额和总价  
1038 - const tkje = parseFloat(px.pxjg) * parseInt(px.projectNumber) || 0;  
1039 - const f_TotalPrice = tkje;  
1040 -  
1041 - // 处理健康师列表  
1042 - const lqHytkJksyjList = (px.lqHytkJksyjList || []).map(jks => ({  
1043 - jks: jks.jks || '',  
1044 - jksxm: jks.jksxm || '',  
1045 - jkszh: jks.jkszh || '',  
1046 - jksyj: parseFloat(jks.jksyj) || 0,  
1047 - f_jsjid: jks.jsjId || '',  
1048 - f_tkpxid: px.px || '',  
1049 - f_LaborCost: parseFloat(jks.laborCost) || 0,  
1050 - f_tkpxNumber: parseInt(px.projectNumber) || 0  
1051 - }));  
1052 -  
1053 - // 处理科技部老师列表  
1054 - const lqHytkKjbsyjList = (px.lqHytkKjbsyjList || []).map(kjb => ({  
1055 - kjbls: kjb.kjbls || '',  
1056 - kjblsxm: kjb.kjblsxm || '',  
1057 - kjblszh: kjb.kjblszh || '',  
1058 - kjblsyj: parseFloat(kjb.kjblsyj) || 0,  
1059 - f_tkpxid: px.px || '',  
1060 - f_LaborCost: parseFloat(kjb.laborCost) || 0,  
1061 - f_tkpxNumber: parseInt(px.projectNumber) || 0  
1062 - }));  
1063 -  
1064 - return {  
1065 - px: px.px || '',  
1066 - pxmc: px.pxmc || '',  
1067 - pxjg: parseFloat(px.pxjg) || 0,  
1068 - tkje: tkje,  
1069 - f_ProjectNumber: parseInt(px.projectNumber) || 0,  
1070 - f_SourceType: px.qt2 || '',  
1071 - f_TotalPrice: f_TotalPrice,  
1072 - lqHytkJksyjList: lqHytkJksyjList,  
1073 - lqHytkKjbsyjList: lqHytkKjbsyjList  
1074 - };  
1075 - });  
1076 - },  
1077 - // 品项健康师相关方法  
1078 - addPxJks(pxIndex) {  
1079 - if (!this.dataForm.lqHytkMxList[pxIndex].lqHytkJksyjList) {  
1080 - this.$set(this.dataForm.lqHytkMxList[pxIndex], 'lqHytkJksyjList', []);  
1081 - }  
1082 - // 获取当前品项的手工费  
1083 - const currentPx = this.dataForm.lqHytkMxList[pxIndex];  
1084 - const pxLaborCost = currentPx.sgf || 0;  
1085 - const defaultNumber = 1;  
1086 - const laborCost = pxLaborCost * defaultNumber; // 品项手工费 × 次数  
1087 -  
1088 - let item = {  
1089 - "jks": "",  
1090 - "jksxm": "",  
1091 - "jkszh": "",  
1092 - "jksyj": "",  
1093 - "jsjId": "",  
1094 - "laborCost": laborCost, // 品项手工费 × 次数  
1095 - "kdpxNumber": defaultNumber // 默认次数为1  
1096 } 1072 }
1097 - this.dataForm.lqHytkMxList[pxIndex].lqHytkJksyjList.push(item);  
1098 - console.log('添加健康师:', {  
1099 - pxLaborCost,  
1100 - defaultNumber,  
1101 - laborCost,  
1102 - formula: `${pxLaborCost} × ${defaultNumber} = ${laborCost}`  
1103 - });  
1104 - },  
1105 - removePxJks(pxIndex, jksIndex) {  
1106 - this.dataForm.lqHytkMxList[pxIndex].lqHytkJksyjList.splice(jksIndex, 1);  
1107 - },  
1108 - // 品项科技部老师相关方法  
1109 - addPxKjb(pxIndex) {  
1110 - if (!this.dataForm.lqHytkMxList[pxIndex].lqHytkKjbsyjList) {  
1111 - this.$set(this.dataForm.lqHytkMxList[pxIndex], 'lqHytkKjbsyjList', []);  
1112 - }  
1113 - // 获取当前品项的手工费  
1114 - const currentPx = this.dataForm.lqHytkMxList[pxIndex];  
1115 - const pxLaborCost = currentPx.sgf || 0;  
1116 - const defaultNumber = 1;  
1117 - const laborCost = pxLaborCost * defaultNumber; // 品项手工费 × 次数  
1118 -  
1119 - let item = {  
1120 - "kjbls": "",  
1121 - "kjblsyj": "",  
1122 - "kjblsxm": "",  
1123 - "kjblszh": "",  
1124 - "laborCost": laborCost, // 品项手工费 × 次数  
1125 - "hdpxNumber": defaultNumber // 默认次数为1  
1126 - }  
1127 - this.dataForm.lqHytkMxList[pxIndex].lqHytkKjbsyjList.push(item);  
1128 - console.log('添加科技部老师:', {  
1129 - pxLaborCost,  
1130 - defaultNumber,  
1131 - laborCost,  
1132 - formula: `${pxLaborCost} × ${defaultNumber} = ${laborCost}`  
1133 - });  
1134 - },  
1135 - removePxKjb(pxIndex, kjbIndex) {  
1136 - this.dataForm.lqHytkMxList[pxIndex].lqHytkKjbsyjList.splice(kjbIndex, 1);  
1137 - },  
1138 - // 加载门店数据并设置默认门店  
1139 - loadStoreDataAndSetDefault() {  
1140 - console.log('开始加载门店数据和用户信息...');  
1141 - // 先加载门店数据  
1142 - this.loadStoreDataPromise().then(() => {  
1143 - // 门店数据加载完成后,获取用户信息  
1144 - return this.getCurrentUserStorePromise();  
1145 - }).then((userData) => {  
1146 - if (userData && userData.mdid) {  
1147 - const userStoreId = userData.mdid;  
1148 - console.log('用户门店ID:', userStoreId);  
1149 - console.log('门店选项列表:', this.mdOptions);  
1150 -  
1151 - // 检查用户门店ID是否在门店列表中  
1152 - const matchingStore = this.mdOptions.find(store => store.id === userStoreId);  
1153 - if (matchingStore) {  
1154 - this.dataForm.md = userStoreId;  
1155 - this.dataForm.mdmc = matchingStore.fullName;  
1156 - this.dataForm.mdbh = matchingStore.id;  
1157 - console.log('找到匹配的门店,设置默认门店ID:', userStoreId);  
1158 - console.log('匹配的门店信息:', matchingStore);  
1159 - } else {  
1160 - console.warn('用户门店ID在门店列表中未找到匹配项');  
1161 - console.log('用户门店ID:', userStoreId);  
1162 - console.log('可用门店ID列表:', this.mdOptions.map(s => s.id));  
1163 - }  
1164 - } else {  
1165 - console.warn('用户数据中没有门店ID,无法设置默认值');  
1166 - }  
1167 -  
1168 - // 加载健康师和科技部老师选项  
1169 - this.getjksOptions();  
1170 - this.getkjbOptions();  
1171 - }).catch(err => {  
1172 - console.error('加载数据失败:', err);  
1173 - });  
1174 - },  
1175 - // 加载门店数据  
1176 - loadStoreDataPromise() {  
1177 - // 使用原来的数据接口方式  
1178 - return previewDataInterface('730960205902251269').then(res => {  
1179 - console.log('门店API原始响应:', res);  
1180 - if (res.data && res.data.length > 0) {  
1181 - this.mdOptions = res.data;  
1182 - console.log('门店数据加载成功:', this.mdOptions);  
1183 - return res.data; 1073 + }
  1074 +
  1075 + return true;
  1076 + },
  1077 + // 处理表单数据
  1078 + processFormData() {
  1079 + // 检查是否有科美品项
  1080 + const hasKemei = this.dataForm.lqHytkMxList.some(px => px.qt2 === '科美');
  1081 +
  1082 + // 设置是否有科技部
  1083 + this.dataForm.sfykjb = hasKemei ? "是" : "否";
  1084 +
  1085 + // 处理品项列表,转换为指定格式
  1086 + this.dataForm.lqHytkMxList = this.dataForm.lqHytkMxList.map(px => {
  1087 + // 计算退卡金额和总价
  1088 + const tkje = parseFloat(px.pxjg) * parseInt(px.projectNumber) || 0;
  1089 + const f_TotalPrice = tkje;
  1090 +
  1091 + // 处理健康师列表
  1092 + const lqHytkJksyjList = (px.lqHytkJksyjList || []).map(jks => ({
  1093 + jks: jks.jks || '',
  1094 + jksxm: jks.jksxm || '',
  1095 + jkszh: jks.jkszh || '',
  1096 + jksyj: parseFloat(jks.jksyj) || 0,
  1097 + f_jsjid: jks.jsjId || '',
  1098 + f_tkpxid: px.px || '',
  1099 + f_LaborCost: parseFloat(jks.laborCost) || 0,
  1100 + f_tkpxNumber: parseInt(px.projectNumber) || 0
  1101 + }));
  1102 +
  1103 + // 处理科技部老师列表
  1104 + const lqHytkKjbsyjList = (px.lqHytkKjbsyjList || []).map(kjb => ({
  1105 + kjbls: kjb.kjbls || '',
  1106 + kjblsxm: kjb.kjblsxm || '',
  1107 + kjblszh: kjb.kjblszh || '',
  1108 + kjblsyj: parseFloat(kjb.kjblsyj) || 0,
  1109 + f_tkpxid: px.px || '',
  1110 + f_LaborCost: parseFloat(kjb.laborCost) || 0,
  1111 + f_tkpxNumber: parseInt(px.projectNumber) || 0
  1112 + }));
  1113 +
  1114 + return {
  1115 + px: px.px || '',
  1116 + pxmc: px.pxmc || '',
  1117 + pxjg: parseFloat(px.pxjg) || 0,
  1118 + tkje: tkje,
  1119 + f_ProjectNumber: parseInt(px.projectNumber) || 0,
  1120 + f_SourceType: px.qt2 || '',
  1121 + f_TotalPrice: f_TotalPrice,
  1122 + lqHytkJksyjList: lqHytkJksyjList,
  1123 + lqHytkKjbsyjList: lqHytkKjbsyjList
  1124 + };
  1125 + });
  1126 + },
  1127 + // 品项健康师相关方法
  1128 + addPxJks(pxIndex) {
  1129 + if (!this.dataForm.lqHytkMxList[pxIndex].lqHytkJksyjList) {
  1130 + this.$set(this.dataForm.lqHytkMxList[pxIndex], 'lqHytkJksyjList', []);
  1131 + }
  1132 + // 获取当前品项的手工费
  1133 + const currentPx = this.dataForm.lqHytkMxList[pxIndex];
  1134 + const pxLaborCost = currentPx.sgf || 0;
  1135 + const defaultNumber = 1;
  1136 + const laborCost = pxLaborCost * defaultNumber; // 品项手工费 × 次数
  1137 +
  1138 + let item = {
  1139 + "jks": "",
  1140 + "jksxm": "",
  1141 + "jkszh": "",
  1142 + "jksyj": "",
  1143 + "jsjId": "",
  1144 + "laborCost": laborCost, // 品项手工费 × 次数
  1145 + "kdpxNumber": defaultNumber // 默认次数为1
  1146 + }
  1147 + this.dataForm.lqHytkMxList[pxIndex].lqHytkJksyjList.push(item);
  1148 + console.log('添加健康师:', {
  1149 + pxLaborCost,
  1150 + defaultNumber,
  1151 + laborCost,
  1152 + formula: `${pxLaborCost} × ${defaultNumber} = ${laborCost}`
  1153 + });
  1154 + },
  1155 + removePxJks(pxIndex, jksIndex) {
  1156 + this.dataForm.lqHytkMxList[pxIndex].lqHytkJksyjList.splice(jksIndex, 1);
  1157 + },
  1158 + // 品项科技部老师相关方法
  1159 + addPxKjb(pxIndex) {
  1160 + if (!this.dataForm.lqHytkMxList[pxIndex].lqHytkKjbsyjList) {
  1161 + this.$set(this.dataForm.lqHytkMxList[pxIndex], 'lqHytkKjbsyjList', []);
  1162 + }
  1163 + // 获取当前品项的手工费
  1164 + const currentPx = this.dataForm.lqHytkMxList[pxIndex];
  1165 + const pxLaborCost = currentPx.sgf || 0;
  1166 + const defaultNumber = 1;
  1167 + const laborCost = pxLaborCost * defaultNumber; // 品项手工费 × 次数
  1168 +
  1169 + let item = {
  1170 + "kjbls": "",
  1171 + "kjblsyj": "",
  1172 + "kjblsxm": "",
  1173 + "kjblszh": "",
  1174 + "laborCost": laborCost, // 品项手工费 × 次数
  1175 + "hdpxNumber": defaultNumber // 默认次数为1
  1176 + }
  1177 + this.dataForm.lqHytkMxList[pxIndex].lqHytkKjbsyjList.push(item);
  1178 + console.log('添加科技部老师:', {
  1179 + pxLaborCost,
  1180 + defaultNumber,
  1181 + laborCost,
  1182 + formula: `${pxLaborCost} × ${defaultNumber} = ${laborCost}`
  1183 + });
  1184 + },
  1185 + removePxKjb(pxIndex, kjbIndex) {
  1186 + this.dataForm.lqHytkMxList[pxIndex].lqHytkKjbsyjList.splice(kjbIndex, 1);
  1187 + },
  1188 + // 加载门店数据并设置默认门店
  1189 + loadStoreDataAndSetDefault() {
  1190 + console.log('开始加载门店数据和用户信息...');
  1191 + // 先加载门店数据
  1192 + this.loadStoreDataPromise().then(() => {
  1193 + // 门店数据加载完成后,获取用户信息
  1194 + return this.getCurrentUserStorePromise();
  1195 + }).then((userData) => {
  1196 + if (userData && userData.mdid) {
  1197 + const userStoreId = userData.mdid;
  1198 + console.log('用户门店ID:', userStoreId);
  1199 + console.log('门店选项列表:', this.mdOptions);
  1200 +
  1201 + // 检查用户门店ID是否在门店列表中
  1202 + const matchingStore = this.mdOptions.find(store => store.id === userStoreId);
  1203 + if (matchingStore) {
  1204 + this.dataForm.md = userStoreId;
  1205 + this.dataForm.mdmc = matchingStore.fullName;
  1206 + this.dataForm.mdbh = matchingStore.id;
  1207 + console.log('找到匹配的门店,设置默认门店ID:', userStoreId);
  1208 + console.log('匹配的门店信息:', matchingStore);
1184 } else { 1209 } else {
1185 - console.warn('门店数据为空');  
1186 - return []; 1210 + console.warn('用户门店ID在门店列表中未找到匹配项');
  1211 + console.log('用户门店ID:', userStoreId);
  1212 + console.log('可用门店ID列表:', this.mdOptions.map(s => s.id));
1187 } 1213 }
1188 - }).catch(err => {  
1189 - console.error('门店数据加载失败:', err); 1214 + } else {
  1215 + console.warn('用户数据中没有门店ID,无法设置默认值');
  1216 + }
  1217 +
  1218 + // 加载健康师和科技部老师选项
  1219 + this.getjksOptions();
  1220 + this.getkjbOptions();
  1221 + }).catch(err => {
  1222 + console.error('加载数据失败:', err);
  1223 + });
  1224 + },
  1225 + // 加载门店数据
  1226 + loadStoreDataPromise() {
  1227 + // 使用原来的数据接口方式
  1228 + return previewDataInterface('730960205902251269').then(res => {
  1229 + console.log('门店API原始响应:', res);
  1230 + if (res.data && res.data.length > 0) {
  1231 + this.mdOptions = res.data;
  1232 + console.log('门店数据加载成功:', this.mdOptions);
  1233 + return res.data;
  1234 + } else {
  1235 + console.warn('门店数据为空');
1190 return []; 1236 return [];
  1237 + }
  1238 + }).catch(err => {
  1239 + console.error('门店数据加载失败:', err);
  1240 + return [];
  1241 + });
  1242 + },
  1243 + // 获取当前用户门店信息
  1244 + getCurrentUserStorePromise() {
  1245 + return new Promise((resolve, reject) => {
  1246 + getInfo().then(res => {
  1247 + resolve(res.data.userInfo);
  1248 + }).catch(err => {
  1249 + console.error('获取当前用户信息失败:', err);
  1250 + reject(err);
1191 }); 1251 });
1192 - },  
1193 - // 获取当前用户门店信息  
1194 - getCurrentUserStorePromise() {  
1195 - return new Promise((resolve, reject) => {  
1196 - getInfo().then(res => {  
1197 - resolve(res.data.userInfo);  
1198 - }).catch(err => {  
1199 - console.error('获取当前用户信息失败:', err);  
1200 - reject(err);  
1201 - });  
1202 - });  
1203 - },  
1204 - } 1252 + });
  1253 + },
1205 } 1254 }
  1255 +}
1206 </script> 1256 </script>
1207 1257
1208 <style scoped> 1258 <style scoped>
@@ -1577,18 +1627,18 @@ @@ -1577,18 +1627,18 @@
1577 width: 100%; 1627 width: 100%;
1578 min-width: auto; 1628 min-width: auto;
1579 } 1629 }
1580 - 1630 +
1581 .remaining-item-row { 1631 .remaining-item-row {
1582 flex-wrap: wrap; 1632 flex-wrap: wrap;
1583 gap: 8px; 1633 gap: 8px;
1584 } 1634 }
1585 - 1635 +
1586 .item-name { 1636 .item-name {
1587 width: 100%; 1637 width: 100%;
1588 margin-right: 0; 1638 margin-right: 0;
1589 margin-bottom: 4px; 1639 margin-bottom: 4px;
1590 } 1640 }
1591 - 1641 +
1592 .item-price, 1642 .item-price,
1593 .item-quantity, 1643 .item-quantity,
1594 .item-source { 1644 .item-source {
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_hytk_jksyj/LqHytkJksyjEntity.cs
@@ -137,5 +137,11 @@ namespace NCC.Extend.Entitys.lq_hytk_jksyj @@ -137,5 +137,11 @@ namespace NCC.Extend.Entitys.lq_hytk_jksyj
137 /// </summary> 137 /// </summary>
138 [SugarColumn(ColumnName = "F_ItemName")] 138 [SugarColumn(ColumnName = "F_ItemName")]
139 public string ItemName { get; set; } 139 public string ItemName { get; set; }
  140 +
  141 + /// <summary>
  142 + /// 业绩类型
  143 + /// </summary>
  144 + [SugarColumn(ColumnName = "F_PerformanceType")]
  145 + public string PerformanceType { get; set; }
140 } 146 }
141 } 147 }
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_hytk_kjbsyj/LqHytkKjbsyjEntity.cs
@@ -132,5 +132,11 @@ namespace NCC.Extend.Entitys.lq_hytk_kjbsyj @@ -132,5 +132,11 @@ namespace NCC.Extend.Entitys.lq_hytk_kjbsyj
132 /// </summary> 132 /// </summary>
133 [SugarColumn(ColumnName = "F_ItemName")] 133 [SugarColumn(ColumnName = "F_ItemName")]
134 public string ItemName { get; set; } 134 public string ItemName { get; set; }
  135 +
  136 + /// <summary>
  137 + /// 业绩类型
  138 + /// </summary>
  139 + [SugarColumn(ColumnName = "F_PerformanceType")]
  140 + public string PerformanceType { get; set; }
135 } 141 }
136 } 142 }
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_hytk_mx/LqHytkMxEntity.cs
@@ -120,5 +120,11 @@ namespace NCC.Extend.Entitys.lq_hytk_mx @@ -120,5 +120,11 @@ namespace NCC.Extend.Entitys.lq_hytk_mx
120 /// </summary> 120 /// </summary>
121 [SugarColumn(ColumnName = "F_IsEffective")] 121 [SugarColumn(ColumnName = "F_IsEffective")]
122 public int IsEffective { get; set; } = StatusEnum.有效.GetHashCode(); 122 public int IsEffective { get; set; } = StatusEnum.有效.GetHashCode();
  123 +
  124 + /// <summary>
  125 + /// 业绩类型
  126 + /// </summary>
  127 + [SugarColumn(ColumnName = "F_PerformanceType")]
  128 + public string PerformanceType { get; set; }
123 } 129 }
124 } 130 }
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_kd_jksyj/LqKdJksyjEntity.cs
@@ -100,5 +100,11 @@ namespace NCC.Extend.Entitys.lq_kd_jksyj @@ -100,5 +100,11 @@ namespace NCC.Extend.Entitys.lq_kd_jksyj
100 /// </summary> 100 /// </summary>
101 [SugarColumn(ColumnName = "F_ItemName")] 101 [SugarColumn(ColumnName = "F_ItemName")]
102 public string ItemName { get; set; } 102 public string ItemName { get; set; }
  103 +
  104 + /// <summary>
  105 + /// 业绩类型
  106 + /// </summary>
  107 + [SugarColumn(ColumnName = "F_PerformanceType")]
  108 + public string PerformanceType { get; set; }
103 } 109 }
104 } 110 }
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_kd_kjbsyj/LqKdKjbsyjEntity.cs
@@ -100,5 +100,11 @@ namespace NCC.Extend.Entitys.lq_kd_kjbsyj @@ -100,5 +100,11 @@ namespace NCC.Extend.Entitys.lq_kd_kjbsyj
100 /// </summary> 100 /// </summary>
101 [SugarColumn(ColumnName = "F_ItemName")] 101 [SugarColumn(ColumnName = "F_ItemName")]
102 public string ItemName { get; set; } 102 public string ItemName { get; set; }
  103 +
  104 + /// <summary>
  105 + /// 业绩类型
  106 + /// </summary>
  107 + [SugarColumn(ColumnName = "F_PerformanceType")]
  108 + public string PerformanceType { get; set; }
103 } 109 }
104 } 110 }
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_kd_pxmx/LqKdPxmxEntity.cs
@@ -113,5 +113,11 @@ namespace NCC.Extend.Entitys.lq_kd_pxmx @@ -113,5 +113,11 @@ namespace NCC.Extend.Entitys.lq_kd_pxmx
113 /// </summary> 113 /// </summary>
114 [SugarColumn(ColumnName = "F_ActivityId")] 114 [SugarColumn(ColumnName = "F_ActivityId")]
115 public string ActivityId { get; set; } 115 public string ActivityId { get; set; }
  116 +
  117 + /// <summary>
  118 + /// 业绩类型
  119 + /// </summary>
  120 + [SugarColumn(ColumnName = "F_PerformanceType")]
  121 + public string PerformanceType { get; set; }
116 } 122 }
117 } 123 }
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_xh_jksyj/LqXhJksyjEntity.cs
@@ -148,5 +148,11 @@ namespace NCC.Extend.Entitys.lq_xh_jksyj @@ -148,5 +148,11 @@ namespace NCC.Extend.Entitys.lq_xh_jksyj
148 /// </summary> 148 /// </summary>
149 [SugarColumn(ColumnName = "F_ItemName")] 149 [SugarColumn(ColumnName = "F_ItemName")]
150 public string ItemName { get; set; } 150 public string ItemName { get; set; }
  151 +
  152 + /// <summary>
  153 + /// 业绩类型
  154 + /// </summary>
  155 + [SugarColumn(ColumnName = "F_PerformanceType")]
  156 + public string PerformanceType { get; set; }
151 } 157 }
152 } 158 }
153 \ No newline at end of file 159 \ No newline at end of file
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_xh_kjbsyj/LqXhKjbsyjEntity.cs
@@ -130,5 +130,11 @@ namespace NCC.Extend.Entitys.lq_xh_kjbsyj @@ -130,5 +130,11 @@ namespace NCC.Extend.Entitys.lq_xh_kjbsyj
130 /// </summary> 130 /// </summary>
131 [SugarColumn(ColumnName = "F_ItemName")] 131 [SugarColumn(ColumnName = "F_ItemName")]
132 public string ItemName { get; set; } 132 public string ItemName { get; set; }
  133 +
  134 + /// <summary>
  135 + /// 业绩类型
  136 + /// </summary>
  137 + [SugarColumn(ColumnName = "F_PerformanceType")]
  138 + public string PerformanceType { get; set; }
133 } 139 }
134 } 140 }
135 \ No newline at end of file 141 \ No newline at end of file
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_xh_pxmx/LqXhPxmxEntity.cs
@@ -106,5 +106,11 @@ namespace NCC.Extend.Entitys.lq_xh_pxmx @@ -106,5 +106,11 @@ namespace NCC.Extend.Entitys.lq_xh_pxmx
106 /// </summary> 106 /// </summary>
107 [SugarColumn(ColumnName = "F_IsEffective")] 107 [SugarColumn(ColumnName = "F_IsEffective")]
108 public int? IsEffective { get; set; } = 1; 108 public int? IsEffective { get; set; } = 1;
  109 +
  110 + /// <summary>
  111 + /// 业绩类型
  112 + /// </summary>
  113 + [SugarColumn(ColumnName = "F_PerformanceType")]
  114 + public string PerformanceType { get; set; }
109 } 115 }
110 } 116 }
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_yjmxb/LqYjmxbEntity.cs
@@ -112,6 +112,12 @@ namespace NCC.Extend.Entitys.lq_yjmxb @@ -112,6 +112,12 @@ namespace NCC.Extend.Entitys.lq_yjmxb
112 /// </summary> 112 /// </summary>
113 [SugarColumn(ColumnName = "zyj")] 113 [SugarColumn(ColumnName = "zyj")]
114 public string Zyj { get; set; } 114 public string Zyj { get; set; }
  115 +
  116 + /// <summary>
  117 + /// 业绩类型
  118 + /// </summary>
  119 + [SugarColumn(ColumnName = "F_PerformanceType")]
  120 + public string PerformanceType { get; set; }
115 121
116 } 122 }
117 } 123 }
118 \ No newline at end of file 124 \ No newline at end of file
netcore/src/Modularity/Extend/NCC.Extend/LqAttendanceSummaryService.cs
@@ -374,6 +374,169 @@ namespace NCC.Extend @@ -374,6 +374,169 @@ namespace NCC.Extend
374 } 374 }
375 #endregion 375 #endregion
376 376
  377 + #region 生成健康师考勤模拟数据
  378 + /// <summary>
  379 + /// 生成健康师考勤模拟数据
  380 + /// </summary>
  381 + /// <remarks>
  382 + /// 为所有健康师生成指定年月的考勤模拟数据
  383 + ///
  384 + /// 规则:
  385 + /// - 80%以上的健康师出勤天数 >= 21天
  386 + /// - 其他健康师出勤天数随机生成(0-20天)
  387 + /// - 员工状态默认为1(在职)
  388 + ///
  389 + /// 示例请求:
  390 + /// ```json
  391 + /// {
  392 + /// "year": 2025,
  393 + /// "month": 11
  394 + /// }
  395 + /// ```
  396 + /// </remarks>
  397 + /// <param name="year">年份</param>
  398 + /// <param name="month">月份</param>
  399 + /// <returns>生成结果</returns>
  400 + /// <response code="200">成功生成考勤模拟数据</response>
  401 + /// <response code="400">参数错误</response>
  402 + /// <response code="500">生成失败</response>
  403 + [HttpPost("GenerateMockData/{year}/{month}")]
  404 + public async Task<dynamic> GenerateMockData(int year, int month)
  405 + {
  406 + try
  407 + {
  408 + // 验证参数
  409 + if (year < 2000 || year > 3000)
  410 + {
  411 + throw NCCException.Oh("年份参数无效");
  412 + }
  413 + if (month < 1 || month > 12)
  414 + {
  415 + throw NCCException.Oh("月份参数无效,应在1-12之间");
  416 + }
  417 +
  418 + // 查询所有健康师
  419 + var healthCoaches = await _db.Queryable<UserEntity>()
  420 + .Where(u => u.Gw == "健康师" && u.EnabledMark == 1 && (u.DeleteMark == null || u.DeleteMark == 0))
  421 + .Select(u => new { u.Id, u.RealName })
  422 + .ToListAsync();
  423 +
  424 + if (!healthCoaches.Any())
  425 + {
  426 + throw NCCException.Oh("未找到健康师用户");
  427 + }
  428 +
  429 + // 检查是否已存在该年月的考勤数据
  430 + var existingRecords = await _db.Queryable<LqAttendanceSummaryEntity>()
  431 + .Where(a => a.Year == year && a.Month == month)
  432 + .CountAsync();
  433 +
  434 + if (existingRecords > 0)
  435 + {
  436 + throw NCCException.Oh($"已存在{year}年{month}月的考勤数据,请先清空后再生成");
  437 + }
  438 +
  439 + var totalCount = healthCoaches.Count;
  440 + var highAttendanceCount = (int)Math.Ceiling(totalCount * 0.8); // 80%以上,向上取整
  441 + var lowAttendanceCount = totalCount - highAttendanceCount;
  442 +
  443 + var random = new Random();
  444 + var entitiesToInsert = new List<LqAttendanceSummaryEntity>();
  445 + var now = DateTime.Now;
  446 +
  447 + // 生成考勤数据
  448 + for (int i = 0; i < totalCount; i++)
  449 + {
  450 + var healthCoach = healthCoaches[i];
  451 + decimal workDays;
  452 + decimal leaveDays;
  453 + decimal restDays;
  454 +
  455 + if (i < highAttendanceCount)
  456 + {
  457 + // 80%以上的健康师:出勤天数 >= 21天
  458 + workDays = random.Next(21, 31); // 21-30天
  459 + var remainingDays = 30 - workDays;
  460 + // 剩余天数分配给请假和休息
  461 + if (remainingDays > 0)
  462 + {
  463 + leaveDays = random.Next(0, (int)remainingDays + 1);
  464 + restDays = remainingDays - leaveDays;
  465 + }
  466 + else
  467 + {
  468 + leaveDays = 0;
  469 + restDays = 0;
  470 + }
  471 + }
  472 + else
  473 + {
  474 + // 其他20%的健康师:出勤天数 < 21天
  475 + workDays = random.Next(0, 21); // 0-20天
  476 + var remainingDays = 30 - workDays;
  477 + // 剩余天数分配给请假和休息
  478 + if (remainingDays > 0)
  479 + {
  480 + leaveDays = random.Next(0, (int)remainingDays + 1);
  481 + restDays = remainingDays - leaveDays;
  482 + }
  483 + else
  484 + {
  485 + leaveDays = 0;
  486 + restDays = 0;
  487 + }
  488 + }
  489 +
  490 + var entity = new LqAttendanceSummaryEntity
  491 + {
  492 + Id = YitIdHelper.NextId().ToString(),
  493 + UserId = healthCoach.Id,
  494 + Year = year,
  495 + Month = month,
  496 + EmployeeStatus = 1, // 在职
  497 + WorkDays = workDays,
  498 + LeaveDays = leaveDays,
  499 + RestDays = restDays,
  500 + Remark = "模拟数据",
  501 + CreateUser = _userManager.UserId ?? "system",
  502 + CreateTime = now,
  503 + UpdateUser = _userManager.UserId ?? "system",
  504 + UpdateTime = now,
  505 + IsEffective = 1
  506 + };
  507 + entitiesToInsert.Add(entity);
  508 + }
  509 +
  510 + // 批量插入
  511 + await _db.Insertable(entitiesToInsert).ExecuteCommandAsync();
  512 +
  513 + // 统计结果
  514 + var highAttendanceActual = entitiesToInsert.Count(e => e.WorkDays >= 21);
  515 + var highAttendancePercentage = (decimal)highAttendanceActual / totalCount * 100;
  516 +
  517 + return new
  518 + {
  519 + success = true,
  520 + message = "生成考勤模拟数据成功",
  521 + data = new
  522 + {
  523 + year = year,
  524 + month = month,
  525 + totalCount = totalCount,
  526 + highAttendanceCount = highAttendanceActual,
  527 + highAttendancePercentage = Math.Round(highAttendancePercentage, 2),
  528 + generatedCount = entitiesToInsert.Count
  529 + }
  530 + };
  531 + }
  532 + catch (Exception ex)
  533 + {
  534 + _logger.LogError(ex, $"生成健康师考勤模拟数据失败 - 年份: {year}, 月份: {month}");
  535 + throw NCCException.Oh($"生成健康师考勤模拟数据失败:{ex.Message}");
  536 + }
  537 + }
  538 + #endregion
  539 +
377 540
378 } 541 }
379 } 542 }
netcore/src/Modularity/Extend/NCC.Extend/LqHytkHytkService.cs
@@ -354,6 +354,7 @@ namespace NCC.Extend.LqHytkHytk @@ -354,6 +354,7 @@ namespace NCC.Extend.LqHytkHytk
354 TotalPrice = item.F_TotalPrice ?? (item.pxjg * (item.F_ProjectNumber ?? 1)), 354 TotalPrice = item.F_TotalPrice ?? (item.pxjg * (item.F_ProjectNumber ?? 1)),
355 IsEffective = StatusEnum.有效.GetHashCode(), 355 IsEffective = StatusEnum.有效.GetHashCode(),
356 ItemCategory = await _db.Queryable<LqXmzlEntity>().Where(x => x.Id == item.px).Select(x => x.Qt2).FirstAsync(), 356 ItemCategory = await _db.Queryable<LqXmzlEntity>().Where(x => x.Id == item.px).Select(x => x.Qt2).FirstAsync(),
  357 + PerformanceType = await _db.Queryable<LqXmzlEntity>().Where(x => x.Id == item.px).Select(x => x.Fl3).FirstAsync() ?? "",
357 }; 358 };
358 allMxEntities.Add(lqHytkMxEntity); 359 allMxEntities.Add(lqHytkMxEntity);
359 360
@@ -382,7 +383,8 @@ namespace NCC.Extend.LqHytkHytk @@ -382,7 +383,8 @@ namespace NCC.Extend.LqHytkHytk
382 ItemCategory = lqHytkMxEntity.ItemCategory, 383 ItemCategory = lqHytkMxEntity.ItemCategory,
383 ItemId = lqHytkMxEntity.Px, 384 ItemId = lqHytkMxEntity.Px,
384 StoreId = newEntity.Md, 385 StoreId = newEntity.Md,
385 - ItemName = lqHytkMxEntity.Pxmc 386 + ItemName = lqHytkMxEntity.Pxmc,
  387 + PerformanceType = lqHytkMxEntity.PerformanceType
386 } 388 }
387 ); 389 );
388 } 390 }
@@ -413,7 +415,8 @@ namespace NCC.Extend.LqHytkHytk @@ -413,7 +415,8 @@ namespace NCC.Extend.LqHytkHytk
413 ItemCategory = lqHytkMxEntity.ItemCategory, 415 ItemCategory = lqHytkMxEntity.ItemCategory,
414 ItemId = lqHytkMxEntity.Px, 416 ItemId = lqHytkMxEntity.Px,
415 StoreId = newEntity.Md, 417 StoreId = newEntity.Md,
416 - ItemName = lqHytkMxEntity.Pxmc 418 + ItemName = lqHytkMxEntity.Pxmc,
  419 + PerformanceType = lqHytkMxEntity.PerformanceType
417 } 420 }
418 ); 421 );
419 } 422 }
@@ -513,6 +516,7 @@ namespace NCC.Extend.LqHytkHytk @@ -513,6 +516,7 @@ namespace NCC.Extend.LqHytkHytk
513 SourceType = item.F_SourceType, 516 SourceType = item.F_SourceType,
514 TotalPrice = item.F_TotalPrice ?? (item.pxjg * (item.F_ProjectNumber ?? 1)), 517 TotalPrice = item.F_TotalPrice ?? (item.pxjg * (item.F_ProjectNumber ?? 1)),
515 ItemCategory = await _db.Queryable<LqXmzlEntity>().Where(x => x.Id == item.px).Select(x => x.Qt2).FirstAsync(), 518 ItemCategory = await _db.Queryable<LqXmzlEntity>().Where(x => x.Id == item.px).Select(x => x.Qt2).FirstAsync(),
  519 + PerformanceType = await _db.Queryable<LqXmzlEntity>().Where(x => x.Id == item.px).Select(x => x.Fl3).FirstAsync() ?? "",
516 }; 520 };
517 allMxEntities.Add(lqHytkMxEntity); 521 allMxEntities.Add(lqHytkMxEntity);
518 522
@@ -540,7 +544,8 @@ namespace NCC.Extend.LqHytkHytk @@ -540,7 +544,8 @@ namespace NCC.Extend.LqHytkHytk
540 ItemCategory = lqHytkMxEntity.ItemCategory, 544 ItemCategory = lqHytkMxEntity.ItemCategory,
541 ItemId = lqHytkMxEntity.Px, 545 ItemId = lqHytkMxEntity.Px,
542 StoreId = entity.Md, 546 StoreId = entity.Md,
543 - ItemName = lqHytkMxEntity.Pxmc 547 + ItemName = lqHytkMxEntity.Pxmc,
  548 + PerformanceType = lqHytkMxEntity.PerformanceType
544 } 549 }
545 ); 550 );
546 } 551 }
@@ -569,7 +574,8 @@ namespace NCC.Extend.LqHytkHytk @@ -569,7 +574,8 @@ namespace NCC.Extend.LqHytkHytk
569 ItemCategory = lqHytkMxEntity.ItemCategory, 574 ItemCategory = lqHytkMxEntity.ItemCategory,
570 ItemId = lqHytkMxEntity.Px, 575 ItemId = lqHytkMxEntity.Px,
571 StoreId = entity.Md, 576 StoreId = entity.Md,
572 - ItemName = lqHytkMxEntity.Pxmc 577 + ItemName = lqHytkMxEntity.Pxmc,
  578 + PerformanceType = lqHytkMxEntity.PerformanceType
573 } 579 }
574 ); 580 );
575 } 581 }
netcore/src/Modularity/Extend/NCC.Extend/LqKdKdjlbService.cs
@@ -932,6 +932,7 @@ namespace NCC.Extend.LqKdKdjlb @@ -932,6 +932,7 @@ namespace NCC.Extend.LqKdKdjlb
932 IsEffective = StatusEnum.有效.GetHashCode(), 932 IsEffective = StatusEnum.有效.GetHashCode(),
933 ActivityId = input.activityId, 933 ActivityId = input.activityId,
934 ItemCategory = await _db.Queryable<LqXmzlEntity>().Where(x => x.Id == item.px).Select(x => x.Qt2).FirstAsync(), 934 ItemCategory = await _db.Queryable<LqXmzlEntity>().Where(x => x.Id == item.px).Select(x => x.Qt2).FirstAsync(),
  935 + PerformanceType = await _db.Queryable<LqXmzlEntity>().Where(x => x.Id == item.px).Select(x => x.Fl3).FirstAsync() ?? "",
935 }; 936 };
936 allPxmxEntities.Add(lqKdPxmxEntity); 937 allPxmxEntities.Add(lqKdPxmxEntity);
937 // 收集该品项关联的健康师业绩 938 // 收集该品项关联的健康师业绩
@@ -957,7 +958,8 @@ namespace NCC.Extend.LqKdKdjlb @@ -957,7 +958,8 @@ namespace NCC.Extend.LqKdKdjlb
957 ItemCategory = lqKdPxmxEntity.ItemCategory, 958 ItemCategory = lqKdPxmxEntity.ItemCategory,
958 ItemId = lqKdPxmxEntity.Px, 959 ItemId = lqKdPxmxEntity.Px,
959 ItemName = lqKdPxmxEntity.Pxmc, 960 ItemName = lqKdPxmxEntity.Pxmc,
960 - StoreId = entity.Djmd 961 + StoreId = entity.Djmd,
  962 + PerformanceType = await _db.Queryable<LqXmzlEntity>().Where(x => x.Id == item.px).Select(x => x.Fl3).FirstAsync() ?? "",
961 }); 963 });
962 } 964 }
963 } 965 }
@@ -982,7 +984,8 @@ namespace NCC.Extend.LqKdKdjlb @@ -982,7 +984,8 @@ namespace NCC.Extend.LqKdKdjlb
982 ItemCategory = lqKdPxmxEntity.ItemCategory, 984 ItemCategory = lqKdPxmxEntity.ItemCategory,
983 ItemId = lqKdPxmxEntity.Px, 985 ItemId = lqKdPxmxEntity.Px,
984 ItemName = lqKdPxmxEntity.Pxmc, 986 ItemName = lqKdPxmxEntity.Pxmc,
985 - StoreId = entity.Djmd 987 + StoreId = entity.Djmd,
  988 + PerformanceType = await _db.Queryable<LqXmzlEntity>().Where(x => x.Id == item.px).Select(x => x.Fl3).FirstAsync() ?? "",
986 } 989 }
987 ); 990 );
988 } 991 }
@@ -1272,6 +1275,7 @@ namespace NCC.Extend.LqKdKdjlb @@ -1272,6 +1275,7 @@ namespace NCC.Extend.LqKdKdjlb
1272 IsEffective = StatusEnum.有效.GetHashCode(), 1275 IsEffective = StatusEnum.有效.GetHashCode(),
1273 ActivityId = input.activityId, 1276 ActivityId = input.activityId,
1274 ItemCategory = await _db.Queryable<LqXmzlEntity>().Where(x => x.Id == item.px).Select(x => x.Qt2).FirstAsync(), 1277 ItemCategory = await _db.Queryable<LqXmzlEntity>().Where(x => x.Id == item.px).Select(x => x.Qt2).FirstAsync(),
  1278 + PerformanceType = await _db.Queryable<LqXmzlEntity>().Where(x => x.Id == item.px).Select(x => x.Fl3).FirstAsync() ?? "",
1275 }; 1279 };
1276 allPxmxEntities.Add(lqKdPxmxEntity); 1280 allPxmxEntities.Add(lqKdPxmxEntity);
1277 1281
@@ -1298,6 +1302,7 @@ namespace NCC.Extend.LqKdKdjlb @@ -1298,6 +1302,7 @@ namespace NCC.Extend.LqKdKdjlb
1298 ItemId = lqKdPxmxEntity.Px, 1302 ItemId = lqKdPxmxEntity.Px,
1299 StoreId = entity.Djmd, 1303 StoreId = entity.Djmd,
1300 ItemName = lqKdPxmxEntity.Pxmc, 1304 ItemName = lqKdPxmxEntity.Pxmc,
  1305 + PerformanceType = lqKdPxmxEntity.PerformanceType,
1301 }); 1306 });
1302 } 1307 }
1303 } 1308 }
@@ -1323,6 +1328,7 @@ namespace NCC.Extend.LqKdKdjlb @@ -1323,6 +1328,7 @@ namespace NCC.Extend.LqKdKdjlb
1323 ItemId = lqKdPxmxEntity.Px, 1328 ItemId = lqKdPxmxEntity.Px,
1324 StoreId = entity.Djmd, 1329 StoreId = entity.Djmd,
1325 ItemName = lqKdPxmxEntity.Pxmc, 1330 ItemName = lqKdPxmxEntity.Pxmc,
  1331 + PerformanceType = lqKdPxmxEntity.PerformanceType,
1326 }); 1332 });
1327 } 1333 }
1328 } 1334 }
@@ -2837,7 +2843,6 @@ namespace NCC.Extend.LqKdKdjlb @@ -2837,7 +2843,6 @@ namespace NCC.Extend.LqKdKdjlb
2837 // 4. 创建退卡品项明细和业绩记录 2843 // 4. 创建退卡品项明细和业绩记录
2838 var refundMxEntities = new List<LqHytkMxEntity>(); 2844 var refundMxEntities = new List<LqHytkMxEntity>();
2839 var refundJksyjEntities = new List<LqHytkJksyjEntity>(); 2845 var refundJksyjEntities = new List<LqHytkJksyjEntity>();
2840 -  
2841 var refundKjbsyjEntities = new List<LqHytkKjbsyjEntity>(); 2846 var refundKjbsyjEntities = new List<LqHytkKjbsyjEntity>();
2842 2847
2843 foreach (var item in input.TransferItems) 2848 foreach (var item in input.TransferItems)
@@ -2863,6 +2868,7 @@ namespace NCC.Extend.LqKdKdjlb @@ -2863,6 +2868,7 @@ namespace NCC.Extend.LqKdKdjlb
2863 TotalPrice = totalItemDeduction, 2868 TotalPrice = totalItemDeduction,
2864 IsEffective = StatusEnum.有效.GetHashCode(), 2869 IsEffective = StatusEnum.有效.GetHashCode(),
2865 ItemCategory = await _db.Queryable<LqXmzlEntity>().Where(x => x.Id == refundPxmxEntity.Px).Select(x => x.Qt2).FirstAsync(), 2870 ItemCategory = await _db.Queryable<LqXmzlEntity>().Where(x => x.Id == refundPxmxEntity.Px).Select(x => x.Qt2).FirstAsync(),
  2871 + PerformanceType = await _db.Queryable<LqXmzlEntity>().Where(x => x.Id == refundPxmxEntity.Px).Select(x => x.Fl3).FirstAsync() ?? "",
2866 }; 2872 };
2867 refundMxEntities.Add(refundMxEntity); 2873 refundMxEntities.Add(refundMxEntity);
2868 var refundKdyjEntities = _db.Queryable<LqKdJksyjEntity>().Where(p => p.Kdpxid == item.BillingItemId).ToList(); 2874 var refundKdyjEntities = _db.Queryable<LqKdJksyjEntity>().Where(p => p.Kdpxid == item.BillingItemId).ToList();
@@ -2885,7 +2891,7 @@ namespace NCC.Extend.LqKdKdjlb @@ -2885,7 +2891,7 @@ namespace NCC.Extend.LqKdKdjlb
2885 Jks = jks.Jkszh, 2891 Jks = jks.Jkszh,
2886 Jksxm = jks.Jksxm, 2892 Jksxm = jks.Jksxm,
2887 Jkszh = jks.Jkszh, 2893 Jkszh = jks.Jkszh,
2888 - Jksyj = (totalItemDeduction / refundKdyjEntities.Count()), 2894 + Jksyj = totalItemDeduction / refundKdyjEntities.Count(),
2889 Tksj = DateTime.Now, 2895 Tksj = DateTime.Now,
2890 F_jsjid = GetMonTeam.JsjId, 2896 F_jsjid = GetMonTeam.JsjId,
2891 F_tkpxid = refundMxEntity.Id, 2897 F_tkpxid = refundMxEntity.Id,
@@ -2897,7 +2903,8 @@ namespace NCC.Extend.LqKdKdjlb @@ -2897,7 +2903,8 @@ namespace NCC.Extend.LqKdKdjlb
2897 ItemCategory = refundMxEntity.ItemCategory, 2903 ItemCategory = refundMxEntity.ItemCategory,
2898 ItemId = refundMxEntity.Px, 2904 ItemId = refundMxEntity.Px,
2899 StoreId = refundEntity.Md, 2905 StoreId = refundEntity.Md,
2900 - ItemName = refundMxEntity.Pxmc 2906 + ItemName = refundMxEntity.Pxmc,
  2907 + PerformanceType = refundMxEntity.PerformanceType
2901 }); 2908 });
2902 } 2909 }
2903 //查询科技部老师的业绩 2910 //查询科技部老师的业绩
@@ -2924,7 +2931,8 @@ namespace NCC.Extend.LqKdKdjlb @@ -2924,7 +2931,8 @@ namespace NCC.Extend.LqKdKdjlb
2924 ItemCategory = refundMxEntity.ItemCategory, 2931 ItemCategory = refundMxEntity.ItemCategory,
2925 ItemId = refundMxEntity.Px, 2932 ItemId = refundMxEntity.Px,
2926 StoreId = refundEntity.Md, 2933 StoreId = refundEntity.Md,
2927 - ItemName = refundMxEntity.Pxmc 2934 + ItemName = refundMxEntity.Pxmc,
  2935 + PerformanceType = refundMxEntity.PerformanceType
2928 }); 2936 });
2929 } 2937 }
2930 } 2938 }
@@ -2967,6 +2975,29 @@ namespace NCC.Extend.LqKdKdjlb @@ -2967,6 +2975,29 @@ namespace NCC.Extend.LqKdKdjlb
2967 foreach (var item in input.TransferItems) 2975 foreach (var item in input.TransferItems)
2968 { 2976 {
2969 var refundPxmxEntity = await _db.Queryable<LqKdPxmxEntity>().Where(p => p.Id == item.BillingItemId).FirstAsync(); 2977 var refundPxmxEntity = await _db.Queryable<LqKdPxmxEntity>().Where(p => p.Id == item.BillingItemId).FirstAsync();
  2978 + // 计算转卡金额和数量
  2979 + var transferAmount = item.ItemPrice * item.TransferQuantity;
  2980 + var transferQuantity = item.TransferQuantity;
  2981 +
  2982 + // 获取原开单品项的总金额和总数量
  2983 + var originalTotalPrice = refundPxmxEntity.TotalPrice > 0 ? refundPxmxEntity.TotalPrice : refundPxmxEntity.ActualPrice;
  2984 + var originalProjectNumber = refundPxmxEntity.ProjectNumber > 0 ? refundPxmxEntity.ProjectNumber : 1;
  2985 +
  2986 + // 计算转卡比例(优先使用金额比例,如果金额为0则使用数量比例)
  2987 + decimal transferRatio = 0;
  2988 + if (originalTotalPrice > 0)
  2989 + {
  2990 + transferRatio = transferAmount / originalTotalPrice;
  2991 + }
  2992 + else if (originalProjectNumber > 0)
  2993 + {
  2994 + transferRatio = (decimal)transferQuantity / originalProjectNumber;
  2995 + }
  2996 + else
  2997 + {
  2998 + transferRatio = 1; // 如果原数据异常,默认按100%计算
  2999 + }
  3000 +
2970 var billingPxmxEntity = new LqKdPxmxEntity 3001 var billingPxmxEntity = new LqKdPxmxEntity
2971 { 3002 {
2972 Id = YitIdHelper.NextId().ToString(), 3003 Id = YitIdHelper.NextId().ToString(),
@@ -2979,53 +3010,142 @@ namespace NCC.Extend.LqKdKdjlb @@ -2979,53 +3010,142 @@ namespace NCC.Extend.LqKdKdjlb
2979 ProjectNumber = item.TransferQuantity, 3010 ProjectNumber = item.TransferQuantity,
2980 IsEnabled = StatusEnum.有效.GetHashCode(), 3011 IsEnabled = StatusEnum.有效.GetHashCode(),
2981 SourceType = refundPxmxEntity.SourceType, 3012 SourceType = refundPxmxEntity.SourceType,
2982 - TotalPrice = item.ItemPrice * item.TransferQuantity,  
2983 - ActualPrice = item.ItemPrice * item.TransferQuantity, 3013 + TotalPrice = transferAmount,
  3014 + ActualPrice = transferAmount,
2984 IsEffective = StatusEnum.有效.GetHashCode(), 3015 IsEffective = StatusEnum.有效.GetHashCode(),
2985 Remark = $"从会员 {fromMember.Khmc} 转入", 3016 Remark = $"从会员 {fromMember.Khmc} 转入",
2986 ItemCategory = await _db.Queryable<LqXmzlEntity>().Where(x => x.Id == refundPxmxEntity.Px).Select(x => x.Qt2).FirstAsync(), 3017 ItemCategory = await _db.Queryable<LqXmzlEntity>().Where(x => x.Id == refundPxmxEntity.Px).Select(x => x.Qt2).FirstAsync(),
  3018 + PerformanceType = await _db.Queryable<LqXmzlEntity>().Where(x => x.Id == refundPxmxEntity.Px).Select(x => x.Fl3).FirstAsync() ?? "",
2987 }; 3019 };
2988 billingPxmxEntities.Add(billingPxmxEntity); 3020 billingPxmxEntities.Add(billingPxmxEntity);
2989 3021
2990 - foreach (var jks in refundJksyjEntities) 3022 + // 查询原开单记录的健康师业绩
  3023 + var billingKdyjEntitiesList = _db.Queryable<LqKdJksyjEntity>().Where(p => p.Kdpxid == item.BillingItemId).ToList();
  3024 + if (billingKdyjEntitiesList.Any())
2991 { 3025 {
2992 - billingJksyjEntities.Add(new LqKdJksyjEntity 3026 + // 计算原开单所有健康师的总业绩
  3027 + var originalTotalJksyj = billingKdyjEntitiesList.Sum(x => decimal.Parse(x.Jksyj ?? "0"));
  3028 + // 如果原开单总业绩为0,则按转卡金额均分
  3029 + if (originalTotalJksyj == 0)
2993 { 3030 {
2994 - Id = YitIdHelper.NextId().ToString(),  
2995 - Glkdbh = billingId,  
2996 - Jks = jks.Jkszh,  
2997 - Jksxm = jks.Jksxm,  
2998 - Jkszh = jks.Jkszh,  
2999 - Jksyj = jks.Jksyj.ToString(),  
3000 - Yjsj = transferTime,  
3001 - Jsj_id = jks.F_jsjid,  
3002 - Kdpxid = billingPxmxEntity.Id,  
3003 - IsEffective = StatusEnum.有效.GetHashCode(),  
3004 - ItemCategory = billingPxmxEntity.ItemCategory,  
3005 - ItemId = billingPxmxEntity.Px,  
3006 - StoreId = billingEntity.Djmd,  
3007 - ItemName = billingPxmxEntity.Pxmc  
3008 - }); 3031 + var avgJksyj = transferAmount / billingKdyjEntitiesList.Count;
  3032 + foreach (var jks in billingKdyjEntitiesList)
  3033 + {
  3034 + billingJksyjEntities.Add(new LqKdJksyjEntity
  3035 + {
  3036 + Id = YitIdHelper.NextId().ToString(),
  3037 + Glkdbh = billingId,
  3038 + Jks = jks.Jkszh,
  3039 + Jksxm = jks.Jksxm,
  3040 + Jkszh = jks.Jkszh,
  3041 + Jksyj = avgJksyj.ToString("F2"),
  3042 + Yjsj = transferTime,
  3043 + Jsj_id = jks.Jsj_id,
  3044 + Kdpxid = billingPxmxEntity.Id,
  3045 + IsEffective = StatusEnum.有效.GetHashCode(),
  3046 + ItemCategory = billingPxmxEntity.ItemCategory,
  3047 + ItemId = billingPxmxEntity.Px,
  3048 + StoreId = billingEntity.Djmd,
  3049 + ItemName = billingPxmxEntity.Pxmc,
  3050 + PerformanceType = billingPxmxEntity.PerformanceType
  3051 + });
  3052 + }
  3053 + }
  3054 + else
  3055 + {
  3056 + // 按原业绩比例计算转卡后的业绩
  3057 + foreach (var jks in billingKdyjEntitiesList)
  3058 + {
  3059 + var originalJksyj = decimal.Parse(jks.Jksyj ?? "0");
  3060 + // 计算该健康师在原开单中的业绩占比
  3061 + var jksRatio = originalTotalJksyj > 0 ? originalJksyj / originalTotalJksyj : 0;
  3062 + // 转卡后的业绩 = 转卡金额 × 该健康师的业绩占比
  3063 + var transferJksyj = transferAmount * jksRatio;
  3064 +
  3065 + billingJksyjEntities.Add(new LqKdJksyjEntity
  3066 + {
  3067 + Id = YitIdHelper.NextId().ToString(),
  3068 + Glkdbh = billingId,
  3069 + Jks = jks.Jkszh,
  3070 + Jksxm = jks.Jksxm,
  3071 + Jkszh = jks.Jkszh,
  3072 + Jksyj = transferJksyj.ToString("F2"),
  3073 + Yjsj = transferTime,
  3074 + Jsj_id = jks.Jsj_id,
  3075 + Kdpxid = billingPxmxEntity.Id,
  3076 + IsEffective = StatusEnum.有效.GetHashCode(),
  3077 + ItemCategory = billingPxmxEntity.ItemCategory,
  3078 + ItemId = billingPxmxEntity.Px,
  3079 + StoreId = billingEntity.Djmd,
  3080 + ItemName = billingPxmxEntity.Pxmc,
  3081 + PerformanceType = billingPxmxEntity.PerformanceType
  3082 + });
  3083 + }
  3084 + }
3009 } 3085 }
3010 3086
3011 - foreach (var kjbs in refundKjbsyjEntities) 3087 + // 查询原开单记录的科技部老师业绩
  3088 + var billingKjbsyjEntitiesList = _db.Queryable<LqKdKjbsyjEntity>().Where(p => p.Kdpxid == item.BillingItemId).ToList();
  3089 + if (billingKjbsyjEntitiesList.Any())
3012 { 3090 {
3013 - billingKjbsyjEntities.Add(new LqKdKjbsyjEntity 3091 + // 计算原开单所有科技部老师的总业绩
  3092 + var originalTotalKjbsyj = billingKjbsyjEntitiesList.Sum(x => decimal.Parse(x.Kjblsyj ?? "0"));
  3093 +
  3094 + // 如果原开单总业绩为0,则按转卡金额均分
  3095 + if (originalTotalKjbsyj == 0)
3014 { 3096 {
3015 - Id = YitIdHelper.NextId().ToString(),  
3016 - Glkdbh = billingId,  
3017 - Kjbls = kjbs.Kjbls,  
3018 - Kjblsxm = kjbs.Kjblsxm,  
3019 - Kjblszh = kjbs.Kjblszh,  
3020 - Kjblsyj = kjbs.Kjblsyj.ToString(),  
3021 - Yjsj = transferTime,  
3022 - Kdpxid = billingPxmxEntity.Id,  
3023 - IsEffective = StatusEnum.有效.GetHashCode(),  
3024 - ItemCategory = billingPxmxEntity.ItemCategory,  
3025 - ItemId = billingPxmxEntity.Px,  
3026 - StoreId = billingEntity.Djmd,  
3027 - ItemName = billingPxmxEntity.Pxmc  
3028 - }); 3097 + var avgKjbsyj = transferAmount / billingKjbsyjEntitiesList.Count;
  3098 + foreach (var kjbs in billingKjbsyjEntitiesList)
  3099 + {
  3100 + billingKjbsyjEntities.Add(new LqKdKjbsyjEntity
  3101 + {
  3102 + Id = YitIdHelper.NextId().ToString(),
  3103 + Glkdbh = billingId,
  3104 + Kjbls = kjbs.Kjbls,
  3105 + Kjblsxm = kjbs.Kjblsxm,
  3106 + Kjblszh = kjbs.Kjblszh,
  3107 + Kjblsyj = avgKjbsyj.ToString("F2"),
  3108 + Yjsj = transferTime,
  3109 + Kdpxid = billingPxmxEntity.Id,
  3110 + IsEffective = StatusEnum.有效.GetHashCode(),
  3111 + ItemCategory = billingPxmxEntity.ItemCategory,
  3112 + ItemId = billingPxmxEntity.Px,
  3113 + StoreId = billingEntity.Djmd,
  3114 + ItemName = billingPxmxEntity.Pxmc,
  3115 + PerformanceType = billingPxmxEntity.PerformanceType
  3116 + });
  3117 + }
  3118 + }
  3119 + else
  3120 + {
  3121 + // 按原业绩比例计算转卡后的业绩
  3122 + foreach (var kjbs in billingKjbsyjEntitiesList)
  3123 + {
  3124 + var originalKjbsyj = decimal.Parse(kjbs.Kjblsyj ?? "0");
  3125 + // 计算该科技部老师在原开单中的业绩占比
  3126 + var kjbsRatio = originalTotalKjbsyj > 0 ? originalKjbsyj / originalTotalKjbsyj : 0;
  3127 + // 转卡后的业绩 = 转卡金额 × 该科技部老师的业绩占比
  3128 + var transferKjbsyj = transferAmount * kjbsRatio;
  3129 +
  3130 + billingKjbsyjEntities.Add(new LqKdKjbsyjEntity
  3131 + {
  3132 + Id = YitIdHelper.NextId().ToString(),
  3133 + Glkdbh = billingId,
  3134 + Kjbls = kjbs.Kjbls,
  3135 + Kjblsxm = kjbs.Kjblsxm,
  3136 + Kjblszh = kjbs.Kjblszh,
  3137 + Kjblsyj = transferKjbsyj.ToString("F2"),
  3138 + Yjsj = transferTime,
  3139 + Kdpxid = billingPxmxEntity.Id,
  3140 + IsEffective = StatusEnum.有效.GetHashCode(),
  3141 + ItemCategory = billingPxmxEntity.ItemCategory,
  3142 + ItemId = billingPxmxEntity.Px,
  3143 + StoreId = billingEntity.Djmd,
  3144 + ItemName = billingPxmxEntity.Pxmc,
  3145 + PerformanceType = billingPxmxEntity.PerformanceType
  3146 + });
  3147 + }
  3148 + }
3029 } 3149 }
3030 } 3150 }
3031 //记录转卡日志 3151 //记录转卡日志
netcore/src/Modularity/Extend/NCC.Extend/LqXhHyhkService.cs
@@ -938,6 +938,7 @@ namespace NCC.Extend.LqXhHyhk @@ -938,6 +938,7 @@ namespace NCC.Extend.LqXhHyhk
938 SourceType = item.sourceType, 938 SourceType = item.sourceType,
939 IsEffective = StatusEnum.有效.GetHashCode(), 939 IsEffective = StatusEnum.有效.GetHashCode(),
940 ItemCategory = await _db.Queryable<LqXmzlEntity>().Where(x => x.Id == item.px).Select(x => x.Qt2).FirstAsync(), 940 ItemCategory = await _db.Queryable<LqXmzlEntity>().Where(x => x.Id == item.px).Select(x => x.Qt2).FirstAsync(),
  941 + PerformanceType = await _db.Queryable<LqXmzlEntity>().Where(x => x.Id == item.px).Select(x => x.Fl3).FirstAsync() ?? "",
941 }; 942 };
942 allPxmxEntities.Add(lqXhPxmxEntity); 943 allPxmxEntities.Add(lqXhPxmxEntity);
943 944
@@ -971,7 +972,8 @@ namespace NCC.Extend.LqXhHyhk @@ -971,7 +972,8 @@ namespace NCC.Extend.LqXhHyhk
971 ItemCategory = lqXhPxmxEntity.ItemCategory, 972 ItemCategory = lqXhPxmxEntity.ItemCategory,
972 ItemId = lqXhPxmxEntity.Px, 973 ItemId = lqXhPxmxEntity.Px,
973 StoreId = entity.Md, 974 StoreId = entity.Md,
974 - ItemName = lqXhPxmxEntity.Pxmc 975 + ItemName = lqXhPxmxEntity.Pxmc,
  976 + PerformanceType = lqXhPxmxEntity.PerformanceType
975 } 977 }
976 ); 978 );
977 } 979 }
@@ -1010,7 +1012,8 @@ namespace NCC.Extend.LqXhHyhk @@ -1010,7 +1012,8 @@ namespace NCC.Extend.LqXhHyhk
1010 ItemCategory = lqXhPxmxEntity.ItemCategory, 1012 ItemCategory = lqXhPxmxEntity.ItemCategory,
1011 ItemId = lqXhPxmxEntity.Px, 1013 ItemId = lqXhPxmxEntity.Px,
1012 StoreId = entity.Md, 1014 StoreId = entity.Md,
1013 - ItemName = lqXhPxmxEntity.Pxmc 1015 + ItemName = lqXhPxmxEntity.Pxmc,
  1016 + PerformanceType = lqXhPxmxEntity.PerformanceType
1014 } 1017 }
1015 ); 1018 );
1016 } 1019 }
@@ -1313,6 +1316,7 @@ namespace NCC.Extend.LqXhHyhk @@ -1313,6 +1316,7 @@ namespace NCC.Extend.LqXhHyhk
1313 OvertimeProjectNumber = (decimal)(entity.OvertimeCoefficient * (item.projectNumber ?? 0)), 1316 OvertimeProjectNumber = (decimal)(entity.OvertimeCoefficient * (item.projectNumber ?? 0)),
1314 ProjectNumber = (decimal)((item.projectNumber ?? 0) + (entity.OvertimeCoefficient * (item.projectNumber ?? 0))), 1317 ProjectNumber = (decimal)((item.projectNumber ?? 0) + (entity.OvertimeCoefficient * (item.projectNumber ?? 0))),
1315 ItemCategory = await _db.Queryable<LqXmzlEntity>().Where(x => x.Id == item.px).Select(x => x.Qt2).FirstAsync(), 1318 ItemCategory = await _db.Queryable<LqXmzlEntity>().Where(x => x.Id == item.px).Select(x => x.Qt2).FirstAsync(),
  1319 + PerformanceType = await _db.Queryable<LqXmzlEntity>().Where(x => x.Id == item.px).Select(x => x.Fl3).FirstAsync() ?? "",
1316 }; 1320 };
1317 allPxmxEntities.Add(lqXhPxmxEntity); 1321 allPxmxEntities.Add(lqXhPxmxEntity);
1318 1322
@@ -1346,7 +1350,8 @@ namespace NCC.Extend.LqXhHyhk @@ -1346,7 +1350,8 @@ namespace NCC.Extend.LqXhHyhk
1346 ItemCategory = lqXhPxmxEntity.ItemCategory, 1350 ItemCategory = lqXhPxmxEntity.ItemCategory,
1347 ItemId = lqXhPxmxEntity.Px, 1351 ItemId = lqXhPxmxEntity.Px,
1348 StoreId = entity.Md, 1352 StoreId = entity.Md,
1349 - ItemName = lqXhPxmxEntity.Pxmc 1353 + ItemName = lqXhPxmxEntity.Pxmc,
  1354 + PerformanceType = lqXhPxmxEntity.PerformanceType
1350 } 1355 }
1351 ); 1356 );
1352 } 1357 }
@@ -1384,7 +1389,8 @@ namespace NCC.Extend.LqXhHyhk @@ -1384,7 +1389,8 @@ namespace NCC.Extend.LqXhHyhk
1384 ItemCategory = lqXhPxmxEntity.ItemCategory, 1389 ItemCategory = lqXhPxmxEntity.ItemCategory,
1385 ItemId = lqXhPxmxEntity.Px, 1390 ItemId = lqXhPxmxEntity.Px,
1386 StoreId = entity.Md, 1391 StoreId = entity.Md,
1387 - ItemName = lqXhPxmxEntity.Pxmc 1392 + ItemName = lqXhPxmxEntity.Pxmc,
  1393 + PerformanceType = lqXhPxmxEntity.PerformanceType
1388 }); 1394 });
1389 } 1395 }
1390 } 1396 }
sql/更新历史数据业绩类型字段.sql 0 → 100644
  1 +-- 更新历史数据的业绩类型字段
  2 +-- 业绩类型根据品项表(lq_xmzl)的 fl3 字段来设置
  3 +-- fl3 字段是"分类③-工资用",用于区分不同的业绩类型
  4 +
  5 +-- 1. 更新开单品项表(通过品项ID关联品项表的fl3字段)
  6 +UPDATE lq_kd_pxmx pxmx
  7 +INNER JOIN lq_xmzl xmzl ON pxmx.px = xmzl.F_Id
  8 +SET pxmx.F_PerformanceType = COALESCE(xmzl.fl3, '')
  9 +WHERE (pxmx.F_PerformanceType IS NULL OR pxmx.F_PerformanceType = '')
  10 + AND pxmx.F_IsEffective = 1;
  11 +
  12 +-- 2. 更新开单健康师业绩表(通过品项ID或开单品项明细ID关联品项表的fl3字段)
  13 +UPDATE lq_kd_jksyj jksyj
  14 +LEFT JOIN lq_kd_pxmx pxmx ON jksyj.F_kdpxid = pxmx.F_Id
  15 +LEFT JOIN lq_xmzl xmzl ON COALESCE(jksyj.F_ItemId, pxmx.px) = xmzl.F_Id
  16 +SET jksyj.F_PerformanceType = COALESCE(xmzl.fl3, '')
  17 +WHERE (jksyj.F_PerformanceType IS NULL OR jksyj.F_PerformanceType = '')
  18 + AND jksyj.F_IsEffective = 1
  19 + AND xmzl.F_Id IS NOT NULL;
  20 +
  21 +-- 3. 更新开单科技部老师业绩表(通过品项ID或开单品项明细ID关联品项表的fl3字段)
  22 +UPDATE lq_kd_kjbsyj kjbsyj
  23 +LEFT JOIN lq_kd_pxmx pxmx ON kjbsyj.F_kdpxid = pxmx.F_Id
  24 +LEFT JOIN lq_xmzl xmzl ON COALESCE(kjbsyj.F_ItemId, pxmx.px) = xmzl.F_Id
  25 +SET kjbsyj.F_PerformanceType = COALESCE(xmzl.fl3, '')
  26 +WHERE (kjbsyj.F_PerformanceType IS NULL OR kjbsyj.F_PerformanceType = '')
  27 + AND kjbsyj.F_IsEffective = 1
  28 + AND xmzl.F_Id IS NOT NULL;
  29 +
  30 +-- 4. 更新消耗品项表(通过品项ID关联品项表的fl3字段)
  31 +UPDATE lq_xh_pxmx pxmx
  32 +INNER JOIN lq_xmzl xmzl ON pxmx.px = xmzl.F_Id
  33 +SET pxmx.F_PerformanceType = COALESCE(xmzl.fl3, '')
  34 +WHERE (pxmx.F_PerformanceType IS NULL OR pxmx.F_PerformanceType = '')
  35 + AND (pxmx.F_IsEffective = 1 OR pxmx.F_IsEffective IS NULL);
  36 +
  37 +-- 5. 更新消耗健康师业绩表(通过品项ID关联品项表的fl3字段)
  38 +UPDATE lq_xh_jksyj jksyj
  39 +LEFT JOIN lq_xh_pxmx pxmx ON jksyj.F_kdpxid = pxmx.F_Id
  40 +LEFT JOIN lq_xmzl xmzl ON COALESCE(jksyj.F_ItemId, pxmx.px) = xmzl.F_Id
  41 +SET jksyj.F_PerformanceType = COALESCE(xmzl.fl3, '')
  42 +WHERE (jksyj.F_PerformanceType IS NULL OR jksyj.F_PerformanceType = '')
  43 + AND (jksyj.F_IsEffective = 1 OR jksyj.F_IsEffective IS NULL)
  44 + AND xmzl.F_Id IS NOT NULL;
  45 +
  46 +-- 6. 更新消耗科技部老师业绩表(通过品项ID关联品项表的fl3字段)
  47 +UPDATE lq_xh_kjbsyj kjbsyj
  48 +LEFT JOIN lq_xh_pxmx pxmx ON kjbsyj.F_hkpxid = pxmx.F_Id
  49 +LEFT JOIN lq_xmzl xmzl ON COALESCE(kjbsyj.F_ItemId, pxmx.px) = xmzl.F_Id
  50 +SET kjbsyj.F_PerformanceType = COALESCE(xmzl.fl3, '')
  51 +WHERE (kjbsyj.F_PerformanceType IS NULL OR kjbsyj.F_PerformanceType = '')
  52 + AND (kjbsyj.F_IsEffective = 1 OR kjbsyj.F_IsEffective IS NULL)
  53 + AND xmzl.F_Id IS NOT NULL;
  54 +
  55 +-- 7. 更新退卡明细表(通过品项ID关联品项表的fl3字段)
  56 +UPDATE lq_hytk_mx mx
  57 +INNER JOIN lq_xmzl xmzl ON mx.px = xmzl.F_Id
  58 +SET mx.F_PerformanceType = COALESCE(xmzl.fl3, '')
  59 +WHERE (mx.F_PerformanceType IS NULL OR mx.F_PerformanceType = '')
  60 + AND mx.F_IsEffective = 1;
  61 +
  62 +-- 8. 更新退卡健康师业绩表(通过品项ID关联品项表的fl3字段)
  63 +UPDATE lq_hytk_jksyj jksyj
  64 +LEFT JOIN lq_hytk_mx mx ON jksyj.F_CardReturn = mx.F_Id
  65 +LEFT JOIN lq_xmzl xmzl ON COALESCE(jksyj.F_ItemId, mx.px) = xmzl.F_Id
  66 +SET jksyj.F_PerformanceType = COALESCE(xmzl.fl3, '')
  67 +WHERE (jksyj.F_PerformanceType IS NULL OR jksyj.F_PerformanceType = '')
  68 + AND jksyj.F_IsEffective = 1
  69 + AND xmzl.F_Id IS NOT NULL;
  70 +
  71 +-- 9. 更新退卡科技部老师业绩表(通过品项ID关联品项表的fl3字段)
  72 +UPDATE lq_hytk_kjbsyj kjbsyj
  73 +LEFT JOIN lq_hytk_mx mx ON kjbsyj.F_CardReturn = mx.F_Id
  74 +LEFT JOIN lq_xmzl xmzl ON COALESCE(kjbsyj.F_ItemId, mx.px) = xmzl.F_Id
  75 +SET kjbsyj.F_PerformanceType = COALESCE(xmzl.fl3, '')
  76 +WHERE (kjbsyj.F_PerformanceType IS NULL OR kjbsyj.F_PerformanceType = '')
  77 + AND kjbsyj.F_IsEffective = 1
  78 + AND xmzl.F_Id IS NOT NULL;
  79 +
  80 +-- 10. 更新业绩明细表(lq_yjmxb)
  81 +-- 业绩明细表通常是汇总表,可能包含开单和消耗的数据
  82 +-- 由于无法准确判断每条记录的具体来源,这里先设置为空
  83 +-- 如果需要更精确的更新,可以根据业务逻辑关联其他表来判断
  84 +-- 例如:如果业绩明细表有开单编号字段,可以关联开单表判断为'开单'
  85 +-- 如果业绩明细表有耗卡编号字段,可以关联耗卡表判断为'消耗'
  86 +UPDATE lq_yjmxb
  87 +SET F_PerformanceType = NULL
  88 +WHERE F_PerformanceType IS NULL OR F_PerformanceType = '';
  89 +
  90 +-- 注意:如果业绩明细表有明确的关联字段,可以使用以下逻辑进行更精确的更新:
  91 +-- UPDATE lq_yjmxb yj
  92 +-- LEFT JOIN lq_kd_kdjlb kd ON yj.关联字段 = kd.F_Id
  93 +-- LEFT JOIN lq_xh_hyhk xh ON yj.关联字段 = xh.F_Id
  94 +-- SET yj.F_PerformanceType = CASE
  95 +-- WHEN kd.F_Id IS NOT NULL THEN '开单'
  96 +-- WHEN xh.F_Id IS NOT NULL THEN '消耗'
  97 +-- ELSE NULL
  98 +-- END
  99 +-- WHERE yj.F_PerformanceType IS NULL OR yj.F_PerformanceType = '';
  100 +
  101 +-- 验证更新结果(统计各表的业绩类型分布)
  102 +SELECT
  103 + 'lq_kd_pxmx' as table_name,
  104 + COUNT(*) as total_count,
  105 + SUM(CASE WHEN F_PerformanceType IS NOT NULL AND F_PerformanceType != '' THEN 1 ELSE 0 END) as '已设置',
  106 + SUM(CASE WHEN F_PerformanceType IS NULL OR F_PerformanceType = '' THEN 1 ELSE 0 END) as '未设置'
  107 +FROM lq_kd_pxmx
  108 +WHERE F_IsEffective = 1
  109 +UNION ALL
  110 +SELECT
  111 + 'lq_kd_jksyj' as table_name,
  112 + COUNT(*) as total_count,
  113 + SUM(CASE WHEN F_PerformanceType IS NOT NULL AND F_PerformanceType != '' THEN 1 ELSE 0 END) as '已设置',
  114 + SUM(CASE WHEN F_PerformanceType IS NULL OR F_PerformanceType = '' THEN 1 ELSE 0 END) as '未设置'
  115 +FROM lq_kd_jksyj
  116 +WHERE F_IsEffective = 1
  117 +UNION ALL
  118 +SELECT
  119 + 'lq_kd_kjbsyj' as table_name,
  120 + COUNT(*) as total_count,
  121 + SUM(CASE WHEN F_PerformanceType IS NOT NULL AND F_PerformanceType != '' THEN 1 ELSE 0 END) as '已设置',
  122 + SUM(CASE WHEN F_PerformanceType IS NULL OR F_PerformanceType = '' THEN 1 ELSE 0 END) as '未设置'
  123 +FROM lq_kd_kjbsyj
  124 +WHERE F_IsEffective = 1
  125 +UNION ALL
  126 +SELECT
  127 + 'lq_xh_pxmx' as table_name,
  128 + COUNT(*) as total_count,
  129 + SUM(CASE WHEN F_PerformanceType IS NOT NULL AND F_PerformanceType != '' THEN 1 ELSE 0 END) as '已设置',
  130 + SUM(CASE WHEN F_PerformanceType IS NULL OR F_PerformanceType = '' THEN 1 ELSE 0 END) as '未设置'
  131 +FROM lq_xh_pxmx
  132 +WHERE F_IsEffective = 1 OR F_IsEffective IS NULL
  133 +UNION ALL
  134 +SELECT
  135 + 'lq_xh_jksyj' as table_name,
  136 + COUNT(*) as total_count,
  137 + SUM(CASE WHEN F_PerformanceType IS NOT NULL AND F_PerformanceType != '' THEN 1 ELSE 0 END) as '已设置',
  138 + SUM(CASE WHEN F_PerformanceType IS NULL OR F_PerformanceType = '' THEN 1 ELSE 0 END) as '未设置'
  139 +FROM lq_xh_jksyj
  140 +WHERE F_IsEffective = 1 OR F_IsEffective IS NULL
  141 +UNION ALL
  142 +SELECT
  143 + 'lq_xh_kjbsyj' as table_name,
  144 + COUNT(*) as total_count,
  145 + SUM(CASE WHEN F_PerformanceType IS NOT NULL AND F_PerformanceType != '' THEN 1 ELSE 0 END) as '已设置',
  146 + SUM(CASE WHEN F_PerformanceType IS NULL OR F_PerformanceType = '' THEN 1 ELSE 0 END) as '未设置'
  147 +FROM lq_xh_kjbsyj
  148 +WHERE F_IsEffective = 1 OR F_IsEffective IS NULL
  149 +UNION ALL
  150 +SELECT
  151 + 'lq_hytk_mx' as table_name,
  152 + COUNT(*) as total_count,
  153 + SUM(CASE WHEN F_PerformanceType IS NOT NULL AND F_PerformanceType != '' THEN 1 ELSE 0 END) as '已设置',
  154 + SUM(CASE WHEN F_PerformanceType IS NULL OR F_PerformanceType = '' THEN 1 ELSE 0 END) as '未设置'
  155 +FROM lq_hytk_mx
  156 +WHERE F_IsEffective = 1
  157 +UNION ALL
  158 +SELECT
  159 + 'lq_hytk_jksyj' as table_name,
  160 + COUNT(*) as total_count,
  161 + SUM(CASE WHEN F_PerformanceType IS NOT NULL AND F_PerformanceType != '' THEN 1 ELSE 0 END) as '已设置',
  162 + SUM(CASE WHEN F_PerformanceType IS NULL OR F_PerformanceType = '' THEN 1 ELSE 0 END) as '未设置'
  163 +FROM lq_hytk_jksyj
  164 +WHERE F_IsEffective = 1
  165 +UNION ALL
  166 +SELECT
  167 + 'lq_hytk_kjbsyj' as table_name,
  168 + COUNT(*) as total_count,
  169 + SUM(CASE WHEN F_PerformanceType IS NOT NULL AND F_PerformanceType != '' THEN 1 ELSE 0 END) as '已设置',
  170 + SUM(CASE WHEN F_PerformanceType IS NULL OR F_PerformanceType = '' THEN 1 ELSE 0 END) as '未设置'
  171 +FROM lq_hytk_kjbsyj
  172 +WHERE F_IsEffective = 1;
  173 +
  174 +-- 查看业绩类型的值分布(从品项表fl3字段)
  175 +SELECT
  176 + 'lq_xmzl.fl3 值分布' as description,
  177 + fl3 as performance_type,
  178 + COUNT(*) as count
  179 +FROM lq_xmzl
  180 +WHERE fl3 IS NOT NULL AND fl3 != ''
  181 +GROUP BY fl3
  182 +ORDER BY count DESC;
  183 +
sql/添加业绩类型字段.sql 0 → 100644
  1 +-- 添加业绩类型字段到相关表
  2 +-- 字段名:F_PerformanceType
  3 +-- 字段类型:varchar(50)
  4 +-- 字段说明:业绩类型
  5 +
  6 +-- 1. 开单品项表
  7 +ALTER TABLE lq_kd_pxmx
  8 +ADD COLUMN F_PerformanceType VARCHAR(50) NULL COMMENT '业绩类型' AFTER F_ActivityId;
  9 +
  10 +-- 2. 开单健康师业绩表
  11 +ALTER TABLE lq_kd_jksyj
  12 +ADD COLUMN F_PerformanceType VARCHAR(50) NULL COMMENT '业绩类型' AFTER F_ItemName;
  13 +
  14 +-- 3. 开单科技部老师业绩表
  15 +ALTER TABLE lq_kd_kjbsyj
  16 +ADD COLUMN F_PerformanceType VARCHAR(50) NULL COMMENT '业绩类型' AFTER F_ItemName;
  17 +
  18 +-- 4. 消耗品项表
  19 +ALTER TABLE lq_xh_pxmx
  20 +ADD COLUMN F_PerformanceType VARCHAR(50) NULL COMMENT '业绩类型' AFTER F_IsEffective;
  21 +
  22 +-- 5. 消耗健康师业绩表
  23 +ALTER TABLE lq_xh_jksyj
  24 +ADD COLUMN F_PerformanceType VARCHAR(50) NULL COMMENT '业绩类型' AFTER F_ItemName;
  25 +
  26 +-- 6. 消耗科技部老师业绩表
  27 +ALTER TABLE lq_xh_kjbsyj
  28 +ADD COLUMN F_PerformanceType VARCHAR(50) NULL COMMENT '业绩类型' AFTER F_ItemName;
  29 +
  30 +-- 7. 退卡明细表
  31 +ALTER TABLE lq_hytk_mx
  32 +ADD COLUMN F_PerformanceType VARCHAR(50) NULL COMMENT '业绩类型' AFTER F_IsEffective;
  33 +
  34 +-- 8. 退卡健康师业绩表
  35 +ALTER TABLE lq_hytk_jksyj
  36 +ADD COLUMN F_PerformanceType VARCHAR(50) NULL COMMENT '业绩类型' AFTER F_ItemName;
  37 +
  38 +-- 9. 退卡科技部老师业绩表
  39 +ALTER TABLE lq_hytk_kjbsyj
  40 +ADD COLUMN F_PerformanceType VARCHAR(50) NULL COMMENT '业绩类型' AFTER F_ItemName;
  41 +
  42 +-- 10. 业绩明细表
  43 +ALTER TABLE lq_yjmxb
  44 +ADD COLUMN F_PerformanceType VARCHAR(50) NULL COMMENT '业绩类型' AFTER zyj;
  45 +