Commit c745e72477c57dfe18964fdbfbc7e8cc5a1ed1a6

Authored by 李宇
2 parents 6cd9003c caa83ded

Merge branch 'master' of http://39.98.150.180/antissoft/lvqianmeiye_ERP

antis-ncc-admin/.env.development
1 1 # 开发
2 2  
3 3 VUE_CLI_BABEL_TRANSPILE_MODULES = true
4   -VUE_APP_BASE_API = 'http://lvqian.antissoft.com'
  4 +# VUE_APP_BASE_API = 'http://lvqian.antissoft.com'
  5 +VUE_APP_BASE_API = 'http://localhost:2011'
5 6 VUE_APP_BASE_WSS = 'ws://192.168.110.45:2011/websocket'
... ...
antis-ncc-admin/src/api/extend/salaryCalculation.js 0 → 100644
  1 +import request from '@/utils/request'
  2 +
  3 +// 保存金三角开卡业绩统计数据
  4 +export function saveGoldTriangleStatistics(statisticsMonth) {
  5 + return request({
  6 + url: '/api/Extend/LqStatistics/save-gold-triangle-stats',
  7 + method: 'POST',
  8 + data: { statisticsMonth }
  9 + })
  10 +}
  11 +
  12 +// 保存健康师个人开单业绩统计数据
  13 +export function savePersonalPerformanceStatistics(statisticsMonth) {
  14 + return request({
  15 + url: '/api/Extend/LqStatistics/save-personal-performance-stats',
  16 + method: 'POST',
  17 + data: { statisticsMonth }
  18 + })
  19 +}
  20 +
  21 +// 保存科技部开单业绩统计数据
  22 +export function saveTechPerformanceStatistics(statisticsMonth) {
  23 + return request({
  24 + url: '/api/Extend/LqStatistics/save-tech-performance-stats',
  25 + method: 'POST',
  26 + data: { statisticsMonth }
  27 + })
  28 +}
... ...
antis-ncc-admin/src/utils/define.js
1 1 // 开发环境接口配置
2 2 // JAVA Boot版本对应后端接口地址
3 3 // JAVA Cloud对应网关地址
4   -const APIURl = 'http://localhost:8061'
  4 +const APIURl = 'http://localhost:2011'
5 5  
6 6 module.exports = {
7 7 APIURl: APIURl,
... ...
antis-ncc-admin/src/views/salaryCalculation/index.vue 0 → 100644
  1 +<template>
  2 + <div class="salary-calculation-container">
  3 + <!-- 页面头部 -->
  4 + <div class="header-card">
  5 + <h1 class="title">工资计算与统计系统</h1>
  6 + <p class="subtitle">智能生成各类业绩统计数据,一键完成工资计算</p>
  7 + </div>
  8 +
  9 + <!-- 月份选择区域 -->
  10 + <el-card class="box-card month-selector-card">
  11 + <div slot="header" class="clearfix">
  12 + <span><i class="el-icon-date"></i> 选择统计月份</span>
  13 + <el-button style="float: right; padding: 3px 0" type="text" @click="resetMonth">重置</el-button>
  14 + </div>
  15 + <div class="month-picker-wrapper">
  16 + <el-date-picker
  17 + v-model="statisticsMonth"
  18 + type="month"
  19 + placeholder="选择月份"
  20 + format="yyyy年MM月"
  21 + value-format="yyyyMM"
  22 + :clearable="false"
  23 + class="month-picker"
  24 + >
  25 + </el-date-picker>
  26 + </div>
  27 + </el-card>
  28 +
  29 + <!-- 主要内容区域 - 左右布局 -->
  30 + <div class="main-content">
  31 + <!-- 左侧:统计操作区域 -->
  32 + <div class="left-panel">
  33 + <!-- 一键计算工资 -->
  34 + <el-card class="box-card calculate-card">
  35 + <div slot="header" class="clearfix">
  36 + <span><i class="el-icon-cpu"></i> 一键计算工资</span>
  37 + </div>
  38 + <div class="calculate-content">
  39 + <p class="calculate-desc">按顺序执行所有统计方法,生成完整的工资数据</p>
  40 + <el-button
  41 + type="primary"
  42 + size="large"
  43 + :loading="isCalculating"
  44 + @click="handleCalculateSalary"
  45 + class="calculate-button"
  46 + :disabled="!statisticsMonth"
  47 + >
  48 + <i class="el-icon-magic-stick"></i>
  49 + {{ isCalculating ? '计算中...' : '一键计算工资' }}
  50 + </el-button>
  51 + <div v-if="calculationProgress.length > 0" class="progress-info">
  52 + <div class="progress-title">计算进度:</div>
  53 + <div v-for="(step, index) in calculationProgress" :key="index" class="progress-step">
  54 + <i :class="getProgressIcon(step.status)" :style="{ color: getProgressColor(step.status) }"></i>
  55 + <span :class="{ 'completed': step.status === 'completed', 'failed': step.status === 'failed' }">
  56 + {{ step.name }}
  57 + </span>
  58 + </div>
  59 + </div>
  60 + </div>
  61 + </el-card>
  62 +
  63 + <!-- 单独统计操作 -->
  64 + <el-card class="box-card statistics-card">
  65 + <div slot="header" class="clearfix">
  66 + <span><i class="el-icon-s-operation"></i> 单独统计操作</span>
  67 + </div>
  68 + <div class="statistics-grid">
  69 + <div class="stat-item blue-item">
  70 + <div class="stat-header">
  71 + <i class="el-icon-s-data"></i>
  72 + <span>金三角开卡业绩</span>
  73 + </div>
  74 + <el-button
  75 + type="primary"
  76 + :loading="loadingStates.goldTriangle"
  77 + @click="handleGoldTriangleStatistics"
  78 + class="stat-button"
  79 + :disabled="!statisticsMonth"
  80 + >
  81 + 立即统计
  82 + </el-button>
  83 + </div>
  84 +
  85 + <div class="stat-item green-item">
  86 + <div class="stat-header">
  87 + <i class="el-icon-user"></i>
  88 + <span>健康师个人开单业绩</span>
  89 + </div>
  90 + <el-button
  91 + type="success"
  92 + :loading="loadingStates.personalPerformance"
  93 + @click="handlePersonalPerformanceStatistics"
  94 + class="stat-button"
  95 + :disabled="!statisticsMonth"
  96 + >
  97 + 立即统计
  98 + </el-button>
  99 + </div>
  100 +
  101 + <div class="stat-item orange-item">
  102 + <div class="stat-header">
  103 + <i class="el-icon-s-promotion"></i>
  104 + <span>科技部开单业绩</span>
  105 + </div>
  106 + <el-button
  107 + type="warning"
  108 + :loading="loadingStates.techPerformance"
  109 + @click="handleTechPerformanceStatistics"
  110 + class="stat-button"
  111 + :disabled="!statisticsMonth"
  112 + >
  113 + 立即统计
  114 + </el-button>
  115 + </div>
  116 +
  117 + <!-- 预留位置,用于未来添加更多统计方法 -->
  118 + <div class="stat-item placeholder-item">
  119 + <div class="stat-header">
  120 + <i class="el-icon-plus"></i>
  121 + <span>更多统计方法</span>
  122 + </div>
  123 + <el-button
  124 + type="info"
  125 + disabled
  126 + class="stat-button"
  127 + >
  128 + 敬请期待
  129 + </el-button>
  130 + </div>
  131 + </div>
  132 + </el-card>
  133 + </div>
  134 +
  135 + <!-- 右侧:结果显示区域 -->
  136 + <div class="right-panel">
  137 + <el-card class="box-card result-card">
  138 + <div slot="header" class="clearfix">
  139 + <span><i class="el-icon-document"></i> 统计结果</span>
  140 + <div class="header-actions">
  141 + <el-button type="text" @click="exportResults" :disabled="results.length === 0">
  142 + <i class="el-icon-download"></i> 导出
  143 + </el-button>
  144 + <el-button type="text" @click="clearResults">
  145 + <i class="el-icon-delete"></i> 清空
  146 + </el-button>
  147 + </div>
  148 + </div>
  149 + <div class="result-list" ref="resultList">
  150 + <div v-if="results.length === 0" class="no-results">
  151 + <i class="el-icon-document-copy"></i>
  152 + <p>暂无统计结果</p>
  153 + <p class="no-results-desc">请选择月份并点击上方按钮进行统计</p>
  154 + </div>
  155 + <div v-for="(result, index) in results" :key="index" :class="['result-item', result.success ? 'success-item' : 'error-item']">
  156 + <div class="result-header">
  157 + <i :class="[result.success ? 'el-icon-success' : 'el-icon-error', 'result-icon']"></i>
  158 + <span class="result-title">{{ result.title }}</span>
  159 + <span class="result-time">{{ result.time }}</span>
  160 + </div>
  161 + <pre class="result-content">{{ formatJson(result.data) }}</pre>
  162 + </div>
  163 + </div>
  164 + </el-card>
  165 + </div>
  166 + </div>
  167 + </div>
  168 +</template>
  169 +
  170 +<script>
  171 +import {
  172 + saveGoldTriangleStatistics,
  173 + savePersonalPerformanceStatistics,
  174 + saveTechPerformanceStatistics
  175 +} from '@/api/extend/salaryCalculation'
  176 +
  177 +export default {
  178 + name: 'SalaryCalculation',
  179 + data() {
  180 + return {
  181 + statisticsMonth: this.getCurrentMonth(),
  182 + loadingStates: {
  183 + goldTriangle: false,
  184 + personalPerformance: false,
  185 + techPerformance: false
  186 + },
  187 + results: [], // 存储统计结果,最多保留10条
  188 + isCalculating: false, // 一键计算状态
  189 + calculationProgress: [] // 计算进度
  190 + }
  191 + },
  192 + methods: {
  193 + resetMonth() {
  194 + this.statisticsMonth = this.getCurrentMonth()
  195 + this.$message.info('已重置为当前月份')
  196 + },
  197 + getCurrentMonth() {
  198 + const now = new Date()
  199 + const year = now.getFullYear()
  200 + const month = String(now.getMonth() + 1).padStart(2, '0')
  201 + return `${year}${month}`
  202 + },
  203 + clearResults() {
  204 + this.results = []
  205 + this.calculationProgress = []
  206 + this.$message.info('已清空所有统计结果')
  207 + },
  208 + addResult(newResult) {
  209 + this.results.unshift(newResult) // 添加到数组开头
  210 + if (this.results.length > 10) {
  211 + this.results.pop() // 保持最多10条记录
  212 + }
  213 + this.$nextTick(() => {
  214 + this.$refs.resultList.scrollTop = 0 // 滚动到顶部显示最新结果
  215 + })
  216 + },
  217 + formatJson(json) {
  218 + if (typeof json !== 'string') {
  219 + json = JSON.stringify(json, null, 2)
  220 + }
  221 + return json
  222 + },
  223 + exportResults() {
  224 + if (this.results.length === 0) {
  225 + this.$message.warning('没有可导出的结果')
  226 + return
  227 + }
  228 + // 这里可以实现导出功能
  229 + this.$message.success('导出功能开发中...')
  230 + },
  231 +
  232 + // 一键计算工资
  233 + async handleCalculateSalary() {
  234 + if (!this.statisticsMonth) {
  235 + this.$message.error('请先选择统计月份')
  236 + return
  237 + }
  238 +
  239 + this.isCalculating = true
  240 + this.calculationProgress = []
  241 + this.results = [] // 清空之前的结果
  242 +
  243 + // 定义统计步骤
  244 + const steps = [
  245 + {
  246 + name: '金三角开卡业绩统计',
  247 + method: 'handleGoldTriangleStatistics',
  248 + type: 'gold-triangle'
  249 + },
  250 + {
  251 + name: '健康师个人开单业绩统计',
  252 + method: 'handlePersonalPerformanceStatistics',
  253 + type: 'personal-performance'
  254 + },
  255 + {
  256 + name: '科技部开单业绩统计',
  257 + method: 'handleTechPerformanceStatistics',
  258 + type: 'tech-performance'
  259 + }
  260 + ]
  261 +
  262 + try {
  263 + // 按顺序执行每个统计步骤
  264 + for (let i = 0; i < steps.length; i++) {
  265 + const step = steps[i]
  266 +
  267 + // 更新进度状态
  268 + this.calculationProgress.push({
  269 + name: step.name,
  270 + status: 'running'
  271 + })
  272 +
  273 + try {
  274 + // 调用对应的统计方法
  275 + await this[step.method]()
  276 +
  277 + // 标记为完成
  278 + this.calculationProgress[i].status = 'completed'
  279 +
  280 + // 等待一秒再执行下一步
  281 + if (i < steps.length - 1) {
  282 + await new Promise(resolve => setTimeout(resolve, 1000))
  283 + }
  284 + } catch (error) {
  285 + // 标记为失败
  286 + this.calculationProgress[i].status = 'failed'
  287 + this.$message.error(`${step.name}失败: ${error.message}`)
  288 +
  289 + // 如果某个步骤失败,询问是否继续
  290 + const continueCalc = await this.$confirm(
  291 + `${step.name}执行失败,是否继续执行后续统计?`,
  292 + '统计失败',
  293 + {
  294 + confirmButtonText: '继续',
  295 + cancelButtonText: '停止',
  296 + type: 'warning'
  297 + }
  298 + ).catch(() => false)
  299 +
  300 + if (!continueCalc) {
  301 + break
  302 + }
  303 + }
  304 + }
  305 +
  306 + // 检查是否所有步骤都完成
  307 + const completedCount = this.calculationProgress.filter(p => p.status === 'completed').length
  308 + if (completedCount === steps.length) {
  309 + this.$message.success('工资计算完成!所有统计步骤都已成功执行')
  310 + } else {
  311 + this.$message.warning(`工资计算部分完成,成功执行了 ${completedCount}/${steps.length} 个统计步骤`)
  312 + }
  313 +
  314 + } catch (error) {
  315 + this.$message.error('工资计算过程中发生错误')
  316 + } finally {
  317 + this.isCalculating = false
  318 + }
  319 + },
  320 +
  321 + // 获取进度图标
  322 + getProgressIcon(status) {
  323 + switch (status) {
  324 + case 'running':
  325 + return 'el-icon-loading'
  326 + case 'completed':
  327 + return 'el-icon-success'
  328 + case 'failed':
  329 + return 'el-icon-error'
  330 + default:
  331 + return 'el-icon-time'
  332 + }
  333 + },
  334 +
  335 + // 获取进度颜色
  336 + getProgressColor(status) {
  337 + switch (status) {
  338 + case 'running':
  339 + return '#409EFF'
  340 + case 'completed':
  341 + return '#67C23A'
  342 + case 'failed':
  343 + return '#F56C6C'
  344 + default:
  345 + return '#909399'
  346 + }
  347 + },
  348 +
  349 + // 金三角开卡业绩统计
  350 + async handleGoldTriangleStatistics() {
  351 + this.loadingStates.goldTriangle = true
  352 + try {
  353 + const response = await saveGoldTriangleStatistics(this.statisticsMonth)
  354 + this.addResult({
  355 + type: 'gold-triangle',
  356 + title: '金三角开卡业绩统计',
  357 + success: true,
  358 + data: response.data,
  359 + time: new Date().toLocaleString()
  360 + })
  361 + this.$message.success('金三角开卡业绩统计完成')
  362 + } catch (error) {
  363 + this.addResult({
  364 + type: 'gold-triangle',
  365 + title: '金三角开卡业绩统计',
  366 + success: false,
  367 + data: error.message || '统计失败',
  368 + time: new Date().toLocaleString()
  369 + })
  370 + this.$message.error('金三角开卡业绩统计失败')
  371 + throw error // 重新抛出错误,用于一键计算时的错误处理
  372 + } finally {
  373 + this.loadingStates.goldTriangle = false
  374 + }
  375 + },
  376 +
  377 + // 健康师个人开单业绩统计
  378 + async handlePersonalPerformanceStatistics() {
  379 + this.loadingStates.personalPerformance = true
  380 + try {
  381 + const response = await savePersonalPerformanceStatistics(this.statisticsMonth)
  382 + this.addResult({
  383 + type: 'personal-performance',
  384 + title: '健康师个人开单业绩统计',
  385 + success: true,
  386 + data: response.data,
  387 + time: new Date().toLocaleString()
  388 + })
  389 + this.$message.success('健康师个人开单业绩统计完成')
  390 + } catch (error) {
  391 + this.addResult({
  392 + type: 'personal-performance',
  393 + title: '健康师个人开单业绩统计',
  394 + success: false,
  395 + data: error.message || '统计失败',
  396 + time: new Date().toLocaleString()
  397 + })
  398 + this.$message.error('健康师个人开单业绩统计失败')
  399 + throw error
  400 + } finally {
  401 + this.loadingStates.personalPerformance = false
  402 + }
  403 + },
  404 +
  405 + // 科技部开单业绩统计
  406 + async handleTechPerformanceStatistics() {
  407 + this.loadingStates.techPerformance = true
  408 + try {
  409 + const response = await saveTechPerformanceStatistics(this.statisticsMonth)
  410 + this.addResult({
  411 + type: 'tech-performance',
  412 + title: '科技部开单业绩统计',
  413 + success: true,
  414 + data: response.data,
  415 + time: new Date().toLocaleString()
  416 + })
  417 + this.$message.success('科技部开单业绩统计完成')
  418 + } catch (error) {
  419 + this.addResult({
  420 + type: 'tech-performance',
  421 + title: '科技部开单业绩统计',
  422 + success: false,
  423 + data: error.message || '统计失败',
  424 + time: new Date().toLocaleString()
  425 + })
  426 + this.$message.error('科技部开单业绩统计失败')
  427 + throw error
  428 + } finally {
  429 + this.loadingStates.techPerformance = false
  430 + }
  431 + }
  432 + }
  433 +}
  434 +</script>
  435 +
  436 +<style lang="scss" scoped>
  437 +.salary-calculation-container {
  438 + padding: 20px;
  439 + background-color: #f0f2f5;
  440 + min-height: calc(100vh - 50px);
  441 + font-family: 'Arial', sans-serif;
  442 +
  443 + .header-card {
  444 + background: linear-gradient(135deg, #409EFF, #79BBFF);
  445 + color: #fff;
  446 + padding: 30px;
  447 + border-radius: 15px;
  448 + margin-bottom: 20px;
  449 + text-align: center;
  450 + box-shadow: 0 8px 20px rgba(0, 123, 255, 0.2);
  451 +
  452 + .title {
  453 + font-size: 2.5em;
  454 + margin-bottom: 10px;
  455 + font-weight: bold;
  456 + }
  457 +
  458 + .subtitle {
  459 + font-size: 1.1em;
  460 + opacity: 0.9;
  461 + }
  462 + }
  463 +
  464 + .box-card {
  465 + border-radius: 10px;
  466 + margin-bottom: 20px;
  467 + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
  468 +
  469 + ::v-deep .el-card__header {
  470 + background-color: #fff;
  471 + border-bottom: 1px solid #ebeef5;
  472 + padding: 18px 20px;
  473 + font-size: 1.1em;
  474 + font-weight: bold;
  475 + color: #303133;
  476 + }
  477 +
  478 + ::v-deep .el-card__body {
  479 + padding: 20px;
  480 + }
  481 + }
  482 +
  483 + .month-selector-card {
  484 + .month-picker-wrapper {
  485 + display: flex;
  486 + justify-content: center;
  487 + align-items: center;
  488 + }
  489 + .month-picker {
  490 + width: 100%;
  491 + max-width: 300px;
  492 + }
  493 + }
  494 +
  495 + // 主要内容区域 - 左右布局
  496 + .main-content {
  497 + display: flex;
  498 + gap: 20px;
  499 + min-height: 600px;
  500 +
  501 + .left-panel {
  502 + flex: 1;
  503 + min-width: 0; // 防止flex子项溢出
  504 + }
  505 +
  506 + .right-panel {
  507 + flex: 1;
  508 + min-width: 0;
  509 + }
  510 + }
  511 +
  512 + // 一键计算工资卡片
  513 + .calculate-card {
  514 + margin-bottom: 20px;
  515 + background: linear-gradient(135deg, #67C23A, #85CE61);
  516 + color: white;
  517 +
  518 + ::v-deep .el-card__header {
  519 + background: rgba(255, 255, 255, 0.1);
  520 + color: white;
  521 + border-bottom: 1px solid rgba(255, 255, 255, 0.2);
  522 + }
  523 +
  524 + .calculate-content {
  525 + text-align: center;
  526 +
  527 + .calculate-desc {
  528 + color: rgba(255, 255, 255, 0.9);
  529 + margin-bottom: 20px;
  530 + font-size: 1.1em;
  531 + }
  532 +
  533 + .calculate-button {
  534 + width: 100%;
  535 + height: 60px;
  536 + font-size: 1.3em;
  537 + font-weight: bold;
  538 + border-radius: 10px;
  539 + background: rgba(255, 255, 255, 0.2);
  540 + border: 2px solid rgba(255, 255, 255, 0.3);
  541 + color: white;
  542 +
  543 + &:hover:not(:disabled) {
  544 + background: rgba(255, 255, 255, 0.3);
  545 + border-color: rgba(255, 255, 255, 0.5);
  546 + }
  547 +
  548 + &:disabled {
  549 + opacity: 0.6;
  550 + }
  551 + }
  552 +
  553 + .progress-info {
  554 + margin-top: 20px;
  555 + text-align: left;
  556 +
  557 + .progress-title {
  558 + font-weight: bold;
  559 + margin-bottom: 10px;
  560 + color: rgba(255, 255, 255, 0.9);
  561 + }
  562 +
  563 + .progress-step {
  564 + display: flex;
  565 + align-items: center;
  566 + margin-bottom: 8px;
  567 + font-size: 0.95em;
  568 +
  569 + i {
  570 + margin-right: 8px;
  571 + font-size: 1.1em;
  572 + }
  573 +
  574 + span {
  575 + color: rgba(255, 255, 255, 0.9);
  576 +
  577 + &.completed {
  578 + color: #fff;
  579 + font-weight: bold;
  580 + }
  581 +
  582 + &.failed {
  583 + color: #ffeb3b;
  584 + font-weight: bold;
  585 + }
  586 + }
  587 + }
  588 + }
  589 + }
  590 + }
  591 +
  592 + // 统计操作卡片
  593 + .statistics-card {
  594 + .statistics-grid {
  595 + display: grid;
  596 + grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  597 + gap: 15px;
  598 +
  599 + .stat-item {
  600 + background: #fff;
  601 + border-radius: 8px;
  602 + padding: 15px;
  603 + text-align: center;
  604 + transition: all 0.3s ease;
  605 + border: 2px solid transparent;
  606 +
  607 + &:hover {
  608 + transform: translateY(-2px);
  609 + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
  610 + }
  611 +
  612 + .stat-header {
  613 + margin-bottom: 15px;
  614 +
  615 + i {
  616 + font-size: 1.5em;
  617 + margin-bottom: 8px;
  618 + display: block;
  619 + }
  620 +
  621 + span {
  622 + font-weight: bold;
  623 + font-size: 0.9em;
  624 + color: #333;
  625 + }
  626 + }
  627 +
  628 + .stat-button {
  629 + width: 100%;
  630 + height: 40px;
  631 + font-size: 0.9em;
  632 + border-radius: 6px;
  633 + }
  634 +
  635 + // 不同主题色
  636 + &.blue-item {
  637 + border-color: #409EFF;
  638 + .stat-header i { color: #409EFF; }
  639 + }
  640 +
  641 + &.green-item {
  642 + border-color: #67C23A;
  643 + .stat-header i { color: #67C23A; }
  644 + }
  645 +
  646 + &.orange-item {
  647 + border-color: #E6A23C;
  648 + .stat-header i { color: #E6A23C; }
  649 + }
  650 +
  651 + &.placeholder-item {
  652 + border-color: #C0C4CC;
  653 + background: #f5f7fa;
  654 + .stat-header i { color: #C0C4CC; }
  655 + }
  656 + }
  657 + }
  658 + }
  659 +
  660 + // 结果显示卡片
  661 + .result-card {
  662 + height: 100%;
  663 +
  664 + .header-actions {
  665 + display: flex;
  666 + gap: 10px;
  667 + }
  668 +
  669 + .result-list {
  670 + max-height: 500px;
  671 + overflow-y: auto;
  672 + padding-right: 10px;
  673 +
  674 + .no-results {
  675 + text-align: center;
  676 + color: #909399;
  677 + padding: 40px 20px;
  678 +
  679 + i {
  680 + font-size: 3em;
  681 + margin-bottom: 15px;
  682 + color: #ddd;
  683 + }
  684 +
  685 + p {
  686 + margin: 5px 0;
  687 + font-size: 1.1em;
  688 + }
  689 +
  690 + .no-results-desc {
  691 + font-size: 0.9em;
  692 + color: #bbb;
  693 + }
  694 + }
  695 +
  696 + .result-item {
  697 + border-left: 5px solid;
  698 + padding: 15px;
  699 + margin-bottom: 15px;
  700 + border-radius: 8px;
  701 + background-color: #f9f9f9;
  702 + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
  703 +
  704 + &.success-item {
  705 + border-color: #67C23A;
  706 + }
  707 + &.error-item {
  708 + border-color: #F56C6C;
  709 + }
  710 +
  711 + .result-header {
  712 + display: flex;
  713 + align-items: center;
  714 + margin-bottom: 10px;
  715 + font-weight: bold;
  716 + color: #303133;
  717 +
  718 + .result-icon {
  719 + font-size: 1.2em;
  720 + margin-right: 8px;
  721 + &.el-icon-success {
  722 + color: #67C23A;
  723 + }
  724 + &.el-icon-error {
  725 + color: #F56C6C;
  726 + }
  727 + }
  728 +
  729 + .result-title {
  730 + font-size: 1.1em;
  731 + flex-grow: 1;
  732 + }
  733 +
  734 + .result-time {
  735 + font-size: 0.9em;
  736 + color: #909399;
  737 + }
  738 + }
  739 +
  740 + .result-content {
  741 + background-color: #eee;
  742 + padding: 10px;
  743 + border-radius: 5px;
  744 + white-space: pre-wrap;
  745 + word-break: break-all;
  746 + font-family: 'Consolas', 'Monaco', monospace;
  747 + font-size: 0.9em;
  748 + color: #333;
  749 + }
  750 + }
  751 + }
  752 + }
  753 +}
  754 +
  755 +// 响应式调整
  756 +@media (max-width: 1200px) {
  757 + .main-content {
  758 + flex-direction: column;
  759 + }
  760 +}
  761 +
  762 +@media (max-width: 768px) {
  763 + .salary-calculation-container {
  764 + padding: 10px;
  765 + }
  766 +
  767 + .header-card {
  768 + padding: 20px;
  769 + .title {
  770 + font-size: 1.8em;
  771 + }
  772 + .subtitle {
  773 + font-size: 0.9em;
  774 + }
  775 + }
  776 +
  777 + .statistics-grid {
  778 + grid-template-columns: 1fr !important;
  779 + }
  780 +
  781 + .calculate-button {
  782 + height: 50px !important;
  783 + font-size: 1.1em !important;
  784 + }
  785 +}
  786 +</style>
0 787 \ No newline at end of file
... ...
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdDeductinfo/LqKdDeductinfoCrInput.cs
... ... @@ -9,6 +9,11 @@ namespace NCC.Extend.Entitys.Dto.LqKdDeductinfo
9 9 public class LqKdDeductinfoCrInput
10 10 {
11 11 /// <summary>
  12 + /// 扣减编号
  13 + /// </summary>
  14 + public string id { get; set; }
  15 +
  16 + /// <summary>
12 17 /// 扣减类型
13 18 /// </summary>
14 19 [Required(ErrorMessage = "扣减类型不能为空")]
... ...
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStatistics/SalaryStatisticsInput.cs 0 → 100644
  1 +using System.ComponentModel.DataAnnotations;
  2 +
  3 +namespace NCC.Extend.Entitys.Dto.LqStatistics
  4 +{
  5 + /// <summary>
  6 + /// 工资统计输入参数
  7 + /// </summary>
  8 + public class SalaryStatisticsInput
  9 + {
  10 + /// <summary>
  11 + /// 统计月份(YYYYMM格式)
  12 + /// </summary>
  13 + [Required(ErrorMessage = "统计月份不能为空")]
  14 + [StringLength(6, MinimumLength = 6, ErrorMessage = "统计月份格式错误,请使用YYYYMM格式")]
  15 + public string StatisticsMonth { get; set; }
  16 + }
  17 +}
... ...
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStatisticsTechPerformance/LqStatisticsTechPerformanceListOutput.cs 0 → 100644
  1 +using System;
  2 +
  3 +namespace NCC.Extend.Entitys.Dto.LqStatisticsTechPerformance
  4 +{
  5 + /// <summary>
  6 + /// 科技部开单业绩统计列表输出
  7 + /// </summary>
  8 + public class LqStatisticsTechPerformanceListOutput
  9 + {
  10 + /// <summary>
  11 + /// 主键ID
  12 + /// </summary>
  13 + public string Id { get; set; }
  14 +
  15 + /// <summary>
  16 + /// 统计月份(YYYYMM)
  17 + /// </summary>
  18 + public string StatisticsMonth { get; set; }
  19 +
  20 + /// <summary>
  21 + /// 科技部老师ID
  22 + /// </summary>
  23 + public string TeacherId { get; set; }
  24 +
  25 + /// <summary>
  26 + /// 科技部老师姓名
  27 + /// </summary>
  28 + public string TeacherName { get; set; }
  29 +
  30 + /// <summary>
  31 + /// 科技部老师账号
  32 + /// </summary>
  33 + public string TeacherAccount { get; set; }
  34 +
  35 + /// <summary>
  36 + /// 门店ID
  37 + /// </summary>
  38 + public string StoreId { get; set; }
  39 +
  40 + /// <summary>
  41 + /// 门店名称
  42 + /// </summary>
  43 + public string StoreName { get; set; }
  44 +
  45 + /// <summary>
  46 + /// 订单数量
  47 + /// </summary>
  48 + public int OrderCount { get; set; }
  49 +
  50 + /// <summary>
  51 + /// 总业绩金额
  52 + /// </summary>
  53 + public decimal TotalPerformance { get; set; }
  54 +
  55 + /// <summary>
  56 + /// 人工成本
  57 + /// </summary>
  58 + public decimal LaborCost { get; set; }
  59 +
  60 + /// <summary>
  61 + /// 项目次数
  62 + /// </summary>
  63 + public decimal ProjectCount { get; set; }
  64 +
  65 + /// <summary>
  66 + /// 最后订单日期
  67 + /// </summary>
  68 + public DateTime? LastOrderDate { get; set; }
  69 +
  70 + /// <summary>
  71 + /// 首次订单日期
  72 + /// </summary>
  73 + public DateTime? FirstOrderDate { get; set; }
  74 +
  75 + /// <summary>
  76 + /// 创建时间
  77 + /// </summary>
  78 + public DateTime CreateTime { get; set; }
  79 + }
  80 +}
... ...
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStatisticsTechPerformance/LqStatisticsTechPerformanceListQueryInput.cs 0 → 100644
  1 +using NCC.Common.Filter;
  2 +
  3 +namespace NCC.Extend.Entitys.Dto.LqStatisticsTechPerformance
  4 +{
  5 + /// <summary>
  6 + /// 科技部开单业绩统计列表查询输入
  7 + /// </summary>
  8 + public class LqStatisticsTechPerformanceListQueryInput : PageInputBase
  9 + {
  10 + /// <summary>
  11 + /// 统计月份(YYYYMM)
  12 + /// </summary>
  13 + public string StatisticsMonth { get; set; }
  14 +
  15 + /// <summary>
  16 + /// 科技部老师ID
  17 + /// </summary>
  18 + public string TeacherId { get; set; }
  19 +
  20 + /// <summary>
  21 + /// 科技部老师姓名
  22 + /// </summary>
  23 + public string TeacherName { get; set; }
  24 +
  25 + /// <summary>
  26 + /// 门店ID
  27 + /// </summary>
  28 + public string StoreId { get; set; }
  29 +
  30 + /// <summary>
  31 + /// 门店名称
  32 + /// </summary>
  33 + public string StoreName { get; set; }
  34 + }
  35 +}
... ...
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_kd_jksyj/LqKdJksyjEntity.cs
... ... @@ -64,5 +64,11 @@ namespace NCC.Extend.Entitys.lq_kd_jksyj
64 64 /// </summary>
65 65 [SugarColumn(ColumnName = "F_kdpxid")]
66 66 public string Kdpxid { get; set; }
  67 +
  68 + /// <summary>
  69 + /// 是否有效
  70 + /// </summary>
  71 + [SugarColumn(ColumnName = "F_IsEffective")]
  72 + public int IsEffective { get; set; } = 1;
67 73 }
68 74 }
... ...
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_kd_kdjlb/LqKdKdjlbEntity.cs
... ... @@ -52,7 +52,7 @@ namespace NCC.Extend.Entitys.lq_kd_kdjlb
52 52 /// </summary>
53 53 [SugarColumn(ColumnName = "zdyj")]
54 54 public decimal Zdyj { get; set; }
55   -
  55 +
56 56  
57 57 /// <summary>
58 58 /// 实付业绩
... ... @@ -197,5 +197,12 @@ namespace NCC.Extend.Entitys.lq_kd_kdjlb
197 197 /// </summary>
198 198 [SugarColumn(ColumnName = "F_UpdateTime")]
199 199 public DateTime UpdateTime { get; set; }
  200 +
  201 + /// <summary>
  202 + /// 是否有效
  203 + /// </summary>
  204 + [SugarColumn(ColumnName = "F_IsEffective")]
  205 + public int IsEffective { get; set; } = 1;
  206 +
200 207 }
201 208 }
... ...
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_kd_kjbsyj/LqKdKjbsyjEntity.cs
... ... @@ -64,5 +64,11 @@ namespace NCC.Extend.Entitys.lq_kd_kjbsyj
64 64 /// </summary>
65 65 [SugarColumn(ColumnName = "F_LaborCost")]
66 66 public decimal? LaborCost { get; set; }
  67 +
  68 + /// <summary>
  69 + /// 是否有效
  70 + /// </summary>
  71 + [SugarColumn(ColumnName = "F_IsEffective")]
  72 + public int IsEffective { get; set; } = 1;
67 73 }
68 74 }
... ...
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_kd_pxmx/LqKdPxmxEntity.cs
... ... @@ -82,5 +82,11 @@ namespace NCC.Extend.Entitys.lq_kd_pxmx
82 82 /// </summary>
83 83 [SugarColumn(ColumnName = "F_ActualPrice")]
84 84 public decimal ActualPrice { get; set; }
  85 +
  86 + /// <summary>
  87 + /// 是否有效
  88 + /// </summary>
  89 + [SugarColumn(ColumnName = "F_IsEffective")]
  90 + public int IsEffective { get; set; } = 1;
85 91 }
86 92 }
... ...
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_statistics_tech_performance/LqStatisticsTechPerformanceEntity.cs 0 → 100644
  1 +using System;
  2 +using System.ComponentModel.DataAnnotations;
  3 +using System.ComponentModel.DataAnnotations.Schema;
  4 +using SqlSugar;
  5 +
  6 +namespace NCC.Extend.Entitys.lq_statistics_tech_performance
  7 +{
  8 + /// <summary>
  9 + /// 科技部开单业绩统计数据表
  10 + /// </summary>
  11 + [SugarTable("lq_statistics_tech_performance")]
  12 + public class LqStatisticsTechPerformanceEntity
  13 + {
  14 + /// <summary>
  15 + /// 主键ID
  16 + /// </summary>
  17 + [SugarColumn(ColumnName = "F_Id", IsPrimaryKey = true, Length = 50)]
  18 +
  19 + public string Id { get; set; }
  20 +
  21 + /// <summary>
  22 + /// 统计月份(YYYYMM)
  23 + /// </summary>
  24 + [Required]
  25 + [StringLength(6)]
  26 + [SugarColumn(ColumnName = "F_StatisticsMonth", Length = 6, IsNullable = false)]
  27 + public string StatisticsMonth { get; set; }
  28 +
  29 + /// <summary>
  30 + /// 科技部老师ID
  31 + /// </summary>
  32 + [Required]
  33 + [StringLength(50)]
  34 + [SugarColumn(ColumnName = "F_TeacherId", Length = 50, IsNullable = false)]
  35 + public string TeacherId { get; set; }
  36 +
  37 + /// <summary>
  38 + /// 科技部老师姓名
  39 + /// </summary>
  40 + [Required]
  41 + [StringLength(100)]
  42 + [SugarColumn(ColumnName = "F_TeacherName", Length = 100, IsNullable = false)]
  43 + public string TeacherName { get; set; }
  44 +
  45 + /// <summary>
  46 + /// 科技部老师账号
  47 + /// </summary>
  48 + [StringLength(100)]
  49 + [SugarColumn(ColumnName = "F_TeacherAccount", Length = 100, IsNullable = true)]
  50 + public string TeacherAccount { get; set; }
  51 +
  52 + /// <summary>
  53 + /// 门店ID
  54 + /// </summary>
  55 + [StringLength(50)]
  56 + [SugarColumn(ColumnName = "F_StoreId", Length = 50, IsNullable = true)]
  57 + public string StoreId { get; set; }
  58 +
  59 + /// <summary>
  60 + /// 门店名称
  61 + /// </summary>
  62 + [StringLength(100)]
  63 + [SugarColumn(ColumnName = "F_StoreName", Length = 100, IsNullable = true)]
  64 + public string StoreName { get; set; }
  65 +
  66 + /// <summary>
  67 + /// 订单数量
  68 + /// </summary>
  69 + [SugarColumn(ColumnName = "F_OrderCount", IsNullable = false)]
  70 + public int OrderCount { get; set; } = 0;
  71 +
  72 + /// <summary>
  73 + /// 总业绩金额
  74 + /// </summary>
  75 + [SugarColumn(ColumnName = "F_TotalPerformance", DecimalDigits = 2, IsNullable = false)]
  76 + public decimal TotalPerformance { get; set; } = 0.00m;
  77 +
  78 + /// <summary>
  79 + /// 人工成本
  80 + /// </summary>
  81 + [SugarColumn(ColumnName = "F_LaborCost", DecimalDigits = 2, IsNullable = false)]
  82 + public decimal LaborCost { get; set; } = 0.00m;
  83 +
  84 + /// <summary>
  85 + /// 项目次数
  86 + /// </summary>
  87 + [SugarColumn(ColumnName = "F_ProjectCount", DecimalDigits = 2, IsNullable = false)]
  88 + public decimal ProjectCount { get; set; } = 0.00m;
  89 +
  90 + /// <summary>
  91 + /// 最后订单日期
  92 + /// </summary>
  93 + [SugarColumn(ColumnName = "F_LastOrderDate", IsNullable = true)]
  94 + public DateTime? LastOrderDate { get; set; }
  95 +
  96 + /// <summary>
  97 + /// 首次订单日期
  98 + /// </summary>
  99 + [SugarColumn(ColumnName = "F_FirstOrderDate", IsNullable = true)]
  100 + public DateTime? FirstOrderDate { get; set; }
  101 +
  102 + /// <summary>
  103 + /// 创建时间
  104 + /// </summary>
  105 + [SugarColumn(ColumnName = "F_CreateTime", IsNullable = false)]
  106 + public DateTime CreateTime { get; set; } = DateTime.Now;
  107 + }
  108 +}
... ...
netcore/src/Modularity/Extend/NCC.Extend/LqEventService.cs
... ... @@ -729,25 +729,49 @@ namespace NCC.Extend.LqEvent
729 729  
730 730 try
731 731 {
732   - // 使用多表查询获取门店统计数据
733   - var storeData = await _db.Queryable<LqEventUserEntity, LqMdxxEntity, LqTkjlbEntity>(
  732 + // 第一步:获取门店的目标数据(所有参与活动的用户目标总和)
  733 + var storeTargets = await _db.Queryable<LqEventUserEntity, LqMdxxEntity>(
  734 + (eventUser, store) => eventUser.EventId == eventId && eventUser.StoreId == store.Id
  735 + )
  736 + .GroupBy((eventUser, store) => new { StoreId = store.Id, StoreName = store.Dm })
  737 + .Select(
  738 + (eventUser, store) =>
  739 + new
  740 + {
  741 + StoreId = store.Id,
  742 + StoreName = store.Dm,
  743 + TotalTarget = SqlFunc.AggregateSum(eventUser.EventTarget)
  744 + }
  745 + )
  746 + .ToListAsync();
  747 +
  748 + // 第二步:获取门店的完成数据(拓客记录数量)
  749 + var storeCompletions = await _db.Queryable<LqEventUserEntity, LqMdxxEntity, LqTkjlbEntity>(
734 750 (eventUser, store, tkjlb) => eventUser.EventId == eventId && eventUser.StoreId == store.Id && eventUser.UserId == tkjlb.ExpansionUserId && tkjlb.EventId == eventId
735 751 )
736 752 .GroupBy((eventUser, store, tkjlb) => new { StoreId = store.Id, StoreName = store.Dm })
737 753 .Select(
738 754 (eventUser, store, tkjlb) =>
739   - new StoreDataOutput
  755 + new
740 756 {
741 757 StoreId = store.Id,
742 758 StoreName = store.Dm,
743   - TotalTarget = SqlFunc.AggregateSum(eventUser.EventTarget),
744   - CompletedTarget = SqlFunc.AggregateCount(tkjlb.Id),
745   - CompletionRate = 0, // 将在内存中计算
746   - Ranking = 0, // 将在内存中计算
  759 + CompletedTarget = SqlFunc.AggregateCount(tkjlb.Id)
747 760 }
748 761 )
749 762 .ToListAsync();
750 763  
  764 + // 第三步:合并数据
  765 + var storeData = storeTargets.Select(target => new StoreDataOutput
  766 + {
  767 + StoreId = target.StoreId,
  768 + StoreName = target.StoreName,
  769 + TotalTarget = target.TotalTarget,
  770 + CompletedTarget = storeCompletions.FirstOrDefault(c => c.StoreId == target.StoreId)?.CompletedTarget ?? 0,
  771 + CompletionRate = 0, // 将在内存中计算
  772 + Ranking = 0, // 将在内存中计算
  773 + }).ToList();
  774 +
751 775 // 计算完成率和排名
752 776 foreach (var store in storeData)
753 777 {
... ...
netcore/src/Modularity/Extend/NCC.Extend/LqKdKdjlbService.cs
... ... @@ -799,5 +799,270 @@ namespace NCC.Extend.LqKdKdjlb
799 799 .ToList();
800 800 }
801 801 #endregion
  802 +
  803 + #region 修改开单记录,不做删除,仅健康师业绩、科技部老师业绩信息
  804 + /// <summary>
  805 + /// 修改开单记录,不做删除,仅健康师业绩、科技部老师业绩信息
  806 + /// </summary>
  807 + /// <remarks>
  808 + /// 更新开单记录及其关联的品项明细、健康师业绩、科技部老师业绩信息
  809 + ///
  810 + /// 示例请求:
  811 + /// ```json
  812 + /// {
  813 + /// "id": "开单编号",
  814 + /// "djmd": "单据门店",
  815 + /// "jsj": "金三角",
  816 + /// "kdrq": "2025-01-11",
  817 + /// "lqKdPxmxList": [
  818 + /// {
  819 + /// "px": "品项编号",
  820 + /// "pxmc": "品项名称",
  821 + /// "pxjg": 100.00,
  822 + /// "projectNumber": 1,
  823 + /// "sourceType": "购买",
  824 + /// "lqKdJksyjList": [
  825 + /// {
  826 + /// "jks": "健康师",
  827 + /// "jksxm": "健康师姓名",
  828 + /// "jksyj": "100"
  829 + /// }
  830 + /// ]
  831 + /// }
  832 + /// ]
  833 + /// }
  834 + /// ```
  835 + ///
  836 + /// 参数说明:
  837 + /// - id: 开单记录主键ID
  838 + /// - input: 开单记录更新参数,包含品项明细和业绩信息
  839 + /// </remarks>
  840 + /// <param name="id">开单记录主键ID</param>
  841 + /// <param name="input">开单记录更新参数</param>
  842 + /// <returns>无返回值</returns>
  843 + /// <response code="200">更新成功</response>
  844 + /// <response code="400">参数错误或数据验证失败</response>
  845 + /// <response code="500">服务器内部错误</response>
  846 + [HttpPut("UpdateForNoDelete/{id}")]
  847 + public async Task UpdateForNoDelete(string id, [FromBody] LqKdKdjlbUpInput input)
  848 + {
  849 + var entity = input.Adapt<LqKdKdjlbEntity>();
  850 + entity.Id = id; // 确保ID正确设置
  851 +
  852 + try
  853 + {
  854 + //开启事务
  855 + _db.BeginTran();
  856 +
  857 + // 更新开单记录主表
  858 + await _db.Updateable(entity)
  859 + .IgnoreColumns(ignoreAllNullColumns: true)
  860 + .IgnoreColumns(x => x.CreateTime) // 不更新创建时间
  861 + .ExecuteCommandAsync();
  862 +
  863 + // 处理品项明细列表 - 更新或插入
  864 + if (input.lqKdPxmxList != null && input.lqKdPxmxList.Any())
  865 + {
  866 + foreach (var item in input.lqKdPxmxList)
  867 + {
  868 + // 检查品项明细是否已存在
  869 + var existingPxmx = await _db.Queryable<LqKdPxmxEntity>()
  870 + .Where(x => x.Glkdbh == id && x.Px == item.px)
  871 + .FirstAsync();
  872 +
  873 + if (existingPxmx != null)
  874 + {
  875 + // 更新现有品项明细
  876 + existingPxmx.ProjectNumber = item.projectNumber == 0 ? 1 : item.projectNumber;
  877 + existingPxmx.TotalPrice = (decimal)(item.pxjg * (item.projectNumber == 0 ? 1 : item.projectNumber));
  878 + existingPxmx.Pxmc = item.pxmc;
  879 + existingPxmx.Pxjg = item.pxjg;
  880 + existingPxmx.SourceType = item.sourceType;
  881 + await _db.Updateable(existingPxmx).ExecuteCommandAsync();
  882 +
  883 + // 更新该品项关联的健康师业绩
  884 + if (item.lqKdJksyjList != null && item.lqKdJksyjList.Any())
  885 + {
  886 + // 先删除该品项的所有健康师业绩
  887 + await _db.Deleteable<LqKdJksyjEntity>()
  888 + .Where(x => x.Kdpxid == existingPxmx.Id)
  889 + .ExecuteCommandAsync();
  890 +
  891 + // 重新插入健康师业绩
  892 + var jksyjEntities = item.lqKdJksyjList.Select(ijks_tem => new LqKdJksyjEntity
  893 + {
  894 + Id = YitIdHelper.NextId().ToString(),
  895 + Glkdbh = entity.Id,
  896 + Jks = ijks_tem.jks,
  897 + Jksxm = ijks_tem.jksxm,
  898 + Jkszh = ijks_tem.jkszh,
  899 + Jksyj = ijks_tem.jksyj,
  900 + Yjsj = DateTime.Now,
  901 + Jsj_id = ijks_tem.jsj_id,
  902 + Kdpxid = existingPxmx.Id,
  903 + }).ToList();
  904 +
  905 + if (jksyjEntities.Any())
  906 + {
  907 + await _db.Insertable(jksyjEntities).ExecuteCommandAsync();
  908 + }
  909 + }
  910 +
  911 + // 更新该品项关联的科技部老师业绩
  912 + if (item.lqKdKjbsyjList != null && item.lqKdKjbsyjList.Any())
  913 + {
  914 + // 先删除该品项的所有科技部老师业绩
  915 + await _db.Deleteable<LqKdKjbsyjEntity>()
  916 + .Where(x => x.Kdpxid == existingPxmx.Id)
  917 + .ExecuteCommandAsync();
  918 +
  919 + // 重新插入科技部老师业绩
  920 + var kjbsyjEntities = item.lqKdKjbsyjList.Select(ikjbs_tem => new LqKdKjbsyjEntity
  921 + {
  922 + Id = YitIdHelper.NextId().ToString(),
  923 + Glkdbh = entity.Id,
  924 + Kjbls = ikjbs_tem.kjbls,
  925 + Kjblsxm = ikjbs_tem.kjblsxm,
  926 + Kjblszh = ikjbs_tem.kjblszh,
  927 + Kjblsyj = ikjbs_tem.kjblsyj,
  928 + Yjsj = DateTime.Now,
  929 + Kdpxid = existingPxmx.Id,
  930 + }).ToList();
  931 +
  932 + if (kjbsyjEntities.Any())
  933 + {
  934 + await _db.Insertable(kjbsyjEntities).ExecuteCommandAsync();
  935 + }
  936 + }
  937 + }
  938 + else
  939 + {
  940 + // 插入新的品项明细
  941 + var newPxmxEntity = new LqKdPxmxEntity
  942 + {
  943 + Id = YitIdHelper.NextId().ToString(),
  944 + Glkdbh = entity.Id,
  945 + CreateTIme = DateTime.Now,
  946 + MemberId = entity.Kdhy,
  947 + IsEnabled = 0,
  948 + ProjectNumber = item.projectNumber == 0 ? 1 : item.projectNumber,
  949 + TotalPrice = (decimal)(item.pxjg * (item.projectNumber == 0 ? 1 : item.projectNumber)),
  950 + Px = item.px,
  951 + Pxmc = item.pxmc,
  952 + Pxjg = item.pxjg,
  953 + SourceType = item.sourceType,
  954 + };
  955 + await _db.Insertable(newPxmxEntity).ExecuteCommandAsync();
  956 +
  957 + // 插入该品项关联的健康师业绩
  958 + if (item.lqKdJksyjList != null && item.lqKdJksyjList.Any())
  959 + {
  960 + var jksyjEntities = item.lqKdJksyjList.Select(ijks_tem => new LqKdJksyjEntity
  961 + {
  962 + Id = YitIdHelper.NextId().ToString(),
  963 + Glkdbh = entity.Id,
  964 + Jks = ijks_tem.jks,
  965 + Jksxm = ijks_tem.jksxm,
  966 + Jkszh = ijks_tem.jkszh,
  967 + Jksyj = ijks_tem.jksyj,
  968 + Yjsj = DateTime.Now,
  969 + Jsj_id = ijks_tem.jsj_id,
  970 + Kdpxid = newPxmxEntity.Id,
  971 + }).ToList();
  972 +
  973 + await _db.Insertable(jksyjEntities).ExecuteCommandAsync();
  974 + }
  975 +
  976 + // 插入该品项关联的科技部老师业绩
  977 + if (item.lqKdKjbsyjList != null && item.lqKdKjbsyjList.Any())
  978 + {
  979 + var kjbsyjEntities = item.lqKdKjbsyjList.Select(ikjbs_tem => new LqKdKjbsyjEntity
  980 + {
  981 + Id = YitIdHelper.NextId().ToString(),
  982 + Glkdbh = entity.Id,
  983 + Kjbls = ikjbs_tem.kjbls,
  984 + Kjblsxm = ikjbs_tem.kjblsxm,
  985 + Kjblszh = ikjbs_tem.kjblszh,
  986 + Kjblsyj = ikjbs_tem.kjblsyj,
  987 + Yjsj = DateTime.Now,
  988 + Kdpxid = newPxmxEntity.Id,
  989 + }).ToList();
  990 +
  991 + await _db.Insertable(kjbsyjEntities).ExecuteCommandAsync();
  992 + }
  993 + }
  994 + }
  995 + }
  996 +
  997 + //关闭事务
  998 + _db.CommitTran();
  999 + }
  1000 + catch (Exception)
  1001 + {
  1002 + //回滚事务
  1003 + _db.RollbackTran();
  1004 + throw NCCException.Oh(ErrorCode.COM1001);
  1005 + }
  1006 + }
  1007 + #endregion
  1008 +
  1009 + #region 作废开单记录
  1010 + /// <summary>
  1011 + /// 作废开单记录
  1012 + /// </summary>
  1013 + /// <param name="id">开单记录主键ID</param>
  1014 + /// <returns>无返回值</returns>
  1015 + /// <response code="200">作废成功</response>
  1016 + /// <response code="400">参数错误,开单记录ID不能为空</response>
  1017 + /// <response code="404">开单记录不存在</response>
  1018 + /// <response code="500">服务器内部错误</response>
  1019 + [HttpPut("Cancel/{id}")]
  1020 + public async Task Cancel(string id)
  1021 + {
  1022 + if (string.IsNullOrEmpty(id))
  1023 + {
  1024 + throw NCCException.Oh("开单记录ID不能为空");
  1025 + }
  1026 +
  1027 + try
  1028 + {
  1029 + //开启事务
  1030 + _db.BeginTran();
  1031 +
  1032 + // 查询开单记录
  1033 + var entity = await _db.Queryable<LqKdKdjlbEntity>().FirstAsync(p => p.Id == id);
  1034 + if (entity == null)
  1035 + {
  1036 + throw NCCException.Oh("开单记录不存在");
  1037 + }
  1038 +
  1039 + // 检查是否已经作废
  1040 + if (entity.IsEffective == 0)
  1041 + {
  1042 + throw NCCException.Oh("该开单记录已经作废");
  1043 + }
  1044 +
  1045 + // 标记开单记录为无效
  1046 + entity.IsEffective = 0;
  1047 + await _db.Updateable(entity).ExecuteCommandAsync();
  1048 + // 标记对应开单明细表为无效
  1049 + await _db.Updateable<LqKdPxmxEntity>().SetColumns(it => new LqKdPxmxEntity { IsEffective = 0 }).Where(it => it.Glkdbh == id).ExecuteCommandAsync();
  1050 + // 标记健康师业绩为无效
  1051 + await _db.Updateable<LqKdJksyjEntity>().SetColumns(it => new LqKdJksyjEntity { IsEffective = 0 }).Where(it => it.Glkdbh == id).ExecuteCommandAsync();
  1052 + // 标记科技部老师业绩为无效
  1053 + await _db.Updateable<LqKdKjbsyjEntity>().SetColumns(it => new LqKdKjbsyjEntity { IsEffective = 0 }).Where(it => it.Glkdbh == id).ExecuteCommandAsync();
  1054 + //关闭事务
  1055 + _db.CommitTran();
  1056 + }
  1057 + catch (Exception ex) when (!(ex is NCCException))
  1058 + {
  1059 + //回滚事务
  1060 + _db.RollbackTran();
  1061 + throw NCCException.Oh(ErrorCode.COM1001);
  1062 + }
  1063 + }
  1064 + #endregion
  1065 +
  1066 +
802 1067 }
803 1068 }
... ...
netcore/src/Modularity/Extend/NCC.Extend/LqStatisticsService.cs
... ... @@ -13,6 +13,7 @@ using NCC.Dependency;
13 13 using NCC.DynamicApiController;
14 14 using NCC.Extend.Entitys.Dto.LqMdxx;
15 15 using NCC.Extend.Entitys.Dto.LqStatistics;
  16 +using NCC.Extend.Entitys.Dto.LqStatisticsTechPerformance;
16 17 using NCC.Extend.Entitys.Dto.LqYcsdJsj;
17 18 using NCC.Extend.Entitys.lq_hytk_kjbsyj;
18 19 using NCC.Extend.Entitys.lq_jinsanjiao_user;
... ... @@ -25,6 +26,7 @@ using NCC.Extend.Entitys.lq_ycsd_jsj;
25 26 using NCC.Extend.Entitys.lq_yjmxb;
26 27 using NCC.Extend.Entitys.lq_statistics_gold_triangle;
27 28 using NCC.Extend.Entitys.lq_statistics_personal_performance;
  29 +using NCC.Extend.Entitys.lq_statistics_tech_performance;
28 30 using NCC.Extend.Entitys.lq_xmzl;
29 31 using NCC.Extend.Entitys.Dto.LqStatisticsPersonalPerformance;
30 32 using NCC.Extend.Entitys.v_tech_teacher_flow;
... ... @@ -1190,7 +1192,7 @@ namespace NCC.Extend.LqStatistics
1190 1192 #region 金三角统计数据保存
1191 1193  
1192 1194 /// <summary>
1193   - /// 1、保存金三角开卡业绩统计数据
  1195 + /// 【1】保存金三角开卡业绩统计数据
1194 1196 /// </summary>
1195 1197 /// <remarks>
1196 1198 /// 根据金三角设定和开单记录统计金三角的业绩数据
... ... @@ -1209,14 +1211,16 @@ namespace NCC.Extend.LqStatistics
1209 1211 /// <response code="200">成功保存统计数据</response>
1210 1212 /// <response code="400">参数错误</response>
1211 1213 /// <response code="500">服务器内部错误</response>
1212   - [HttpPost("save-gold-triangle-statistics")]
1213   - public async Task<dynamic> SaveGoldTriangleStatistics(string statisticsMonth)
  1214 + [HttpPost("save-gold-triangle-stats")]
  1215 + public async Task<dynamic> SaveGoldTriangleStatistics([FromBody] SalaryStatisticsInput input)
1214 1216 {
1215   - if (string.IsNullOrEmpty(statisticsMonth) || statisticsMonth.Length != 6)
  1217 + if (input == null || string.IsNullOrEmpty(input.StatisticsMonth) || input.StatisticsMonth.Length != 6)
1216 1218 {
1217 1219 throw NCCException.Oh("统计月份格式错误,请使用YYYYMM格式");
1218 1220 }
1219 1221  
  1222 + var statisticsMonth = input.StatisticsMonth;
  1223 +
1220 1224 try
1221 1225 {
1222 1226 // 使用数据库聚合方式,直接在数据库中完成所有统计计算
... ... @@ -1236,6 +1240,7 @@ namespace NCC.Extend.LqStatistics
1236 1240 jsj.F_Id = jksyj.jsj_id
1237 1241 AND YEAR(jksyj.yjsj) = SUBSTRING(jsj.yf, 1, 4)
1238 1242 AND MONTH(jksyj.yjsj) = SUBSTRING(jsj.yf, 5, 2)
  1243 + AND jksyj.F_IsEffective = 1
1239 1244 )
1240 1245 LEFT JOIN lq_mdxx md ON jsj.md = md.F_Id
1241 1246 WHERE jsj.yf = @statisticsMonth
... ... @@ -1366,7 +1371,7 @@ namespace NCC.Extend.LqStatistics
1366 1371 #region 个人开单业绩统计
1367 1372  
1368 1373 /// <summary>
1369   - /// 保存个人开单业绩统计数据
  1374 + /// 【2】保存健康师个人开单业绩统计数据
1370 1375 /// </summary>
1371 1376 /// <remarks>
1372 1377 /// 根据开单记录统计个人的业绩数据,包括基础业绩和合作业绩
... ... @@ -1386,14 +1391,16 @@ namespace NCC.Extend.LqStatistics
1386 1391 /// <response code="200">成功保存统计数据</response>
1387 1392 /// <response code="400">参数错误</response>
1388 1393 /// <response code="500">服务器内部错误</response>
1389   - [HttpPost("save-personal-performance-statistics")]
1390   - public async Task<dynamic> SavePersonalPerformanceStatistics(string statisticsMonth)
  1394 + [HttpPost("save-personal-performance-stats")]
  1395 + public async Task<dynamic> SavePersonalPerformanceStatistics([FromBody] SalaryStatisticsInput input)
1391 1396 {
1392   - if (string.IsNullOrEmpty(statisticsMonth) || statisticsMonth.Length != 6)
  1397 + if (input == null || string.IsNullOrEmpty(input.StatisticsMonth) || input.StatisticsMonth.Length != 6)
1393 1398 {
1394 1399 throw NCCException.Oh("统计月份格式错误,请使用YYYYMM格式");
1395 1400 }
1396 1401  
  1402 + var statisticsMonth = input.StatisticsMonth;
  1403 +
1397 1404 try
1398 1405 {
1399 1406 // 使用数据库聚合方式,直接在数据库中完成所有统计计算
... ... @@ -1427,7 +1434,7 @@ namespace NCC.Extend.LqStatistics
1427 1434 ) AS BasePerformance,
1428 1435 SUM(CAST(jksyj.jksyj AS DECIMAL(18,2))) AS TotalPerformance
1429 1436 FROM lq_kd_jksyj jksyj
1430   - INNER JOIN lq_kd_pxmx pxmx ON jksyj.F_kdpxid = pxmx.F_Id
  1437 + INNER JOIN lq_kd_pxmx pxmx ON jksyj.F_kdpxid = pxmx.F_Id AND pxmx.F_IsEffective = 1
1431 1438 INNER JOIN lq_xmzl xmzl ON pxmx.px = xmzl.F_Id
1432 1439 INNER JOIN BASE_USER u ON jksyj.jkszh = u.F_Id
1433 1440 LEFT JOIN lq_mdxx md ON u.F_MDID = md.F_Id
... ... @@ -1444,6 +1451,7 @@ namespace NCC.Extend.LqStatistics
1444 1451 AND jksyj.jksyj != '0'
1445 1452 AND jksyj.F_kdpxid IS NOT NULL
1446 1453 AND jksyj.F_kdpxid != ''
  1454 + AND jksyj.F_IsEffective = 1
1447 1455 AND YEAR(jksyj.yjsj) = @year
1448 1456 AND MONTH(jksyj.yjsj) = @month
1449 1457 GROUP BY
... ... @@ -1634,6 +1642,246 @@ namespace NCC.Extend.LqStatistics
1634 1642  
1635 1643 #endregion
1636 1644  
  1645 + #region 科技部开单业绩统计
  1646 +
  1647 + /// <summary>
  1648 + /// 【3】保存科技部开单业绩统计数据
  1649 + /// </summary>
  1650 + /// <remarks>
  1651 + /// 根据指定月份统计科技部老师的开单业绩数据,只统计开卡业绩,不包含耗卡和退卡业绩
  1652 + ///
  1653 + /// 示例请求:
  1654 + /// ```json
  1655 + /// POST /api/Extend/LqStatistics/save-tech-performance-statistics
  1656 + /// {
  1657 + /// "statisticsMonth": "202401"
  1658 + /// }
  1659 + /// ```
  1660 + ///
  1661 + /// 参数说明:
  1662 + /// - statisticsMonth: 统计月份,格式为YYYYMM
  1663 + /// </remarks>
  1664 + /// <param name="statisticsMonth">统计月份(YYYYMM格式)</param>
  1665 + /// <returns>保存结果</returns>
  1666 + /// <response code="200">成功保存统计数据</response>
  1667 + /// <response code="400">参数错误</response>
  1668 + /// <response code="500">服务器内部错误</response>
  1669 + [HttpPost("save-tech-performance-stats")]
  1670 + public async Task<dynamic> SaveTechPerformanceStatistics([FromBody] SalaryStatisticsInput input)
  1671 + {
  1672 + if (input == null || string.IsNullOrEmpty(input.StatisticsMonth) || input.StatisticsMonth.Length != 6)
  1673 + {
  1674 + throw NCCException.Oh("统计月份格式错误,请使用YYYYMM格式");
  1675 + }
  1676 +
  1677 + var statisticsMonth = input.StatisticsMonth;
  1678 +
  1679 + try
  1680 + {
  1681 + // 使用数据库聚合方式,只统计开单业绩(开卡流水)
  1682 + var sql = @"
  1683 + SELECT
  1684 + k.kjbls AS TeacherId,
  1685 + k.kjblsxm AS TeacherName,
  1686 + k.kjblszh AS TeacherAccount,
  1687 + NULL AS StoreId,
  1688 + NULL AS StoreName,
  1689 + COUNT(DISTINCT k.F_kdpxid) AS OrderCount,
  1690 + SUM(CAST(COALESCE(k.kjblsyj, 0) AS DECIMAL(18,2))) AS TotalPerformance,
  1691 + SUM(CAST(COALESCE(k.F_LaborCost, 0) AS DECIMAL(18,2))) AS LaborCost,
  1692 + SUM(CAST(COALESCE(pm.F_ProjectNumber, 0) AS DECIMAL(18,2))) AS ProjectCount,
  1693 + MAX(k.yjsj) AS LastOrderDate,
  1694 + MIN(k.yjsj) AS FirstOrderDate
  1695 + FROM lq_kd_kjbsyj k
  1696 + LEFT JOIN lq_kd_pxmx pm ON k.F_kdpxid = pm.F_Id AND pm.F_IsEffective = 1
  1697 + WHERE k.kjbls IS NOT NULL
  1698 + AND k.kjblsxm IS NOT NULL
  1699 + AND k.yjsj IS NOT NULL
  1700 + AND k.kjblsyj IS NOT NULL
  1701 + AND k.kjblsyj != ''
  1702 + AND k.kjblsyj != '0'
  1703 + AND k.F_IsEffective = 1
  1704 + AND YEAR(k.yjsj) = @year
  1705 + AND MONTH(k.yjsj) = @month
  1706 + GROUP BY
  1707 + k.kjbls,
  1708 + k.kjblsxm,
  1709 + k.kjblszh
  1710 + ORDER BY TotalPerformance DESC";
  1711 +
  1712 + // 解析统计月份
  1713 + var year = int.Parse(statisticsMonth.Substring(0, 4));
  1714 + var month = int.Parse(statisticsMonth.Substring(4, 2));
  1715 +
  1716 + // 执行SQL查询
  1717 + var statisticsData = await _db.Ado.SqlQueryAsync<dynamic>(sql, new { year, month });
  1718 +
  1719 + _logger.LogInformation($"SQL查询结果数量: {statisticsData?.Count ?? 0}");
  1720 + if (statisticsData?.Any() == true)
  1721 + {
  1722 + var firstData = statisticsData.First();
  1723 + _logger.LogInformation($"第一条数据: TeacherId={firstData.TeacherId}, TeacherName={firstData.TeacherName}, TotalPerformance={firstData.TotalPerformance}");
  1724 + }
  1725 +
  1726 + if (!statisticsData.Any())
  1727 + {
  1728 + return new
  1729 + {
  1730 + Success = true,
  1731 + Message = $"未找到 {statisticsMonth} 月份的科技部开单业绩统计数据",
  1732 + SavedCount = 0
  1733 + };
  1734 + }
  1735 +
  1736 + // 转换为实体对象
  1737 + var entities = new List<LqStatisticsTechPerformanceEntity>();
  1738 + foreach (var data in statisticsData)
  1739 + {
  1740 + try
  1741 + {
  1742 + var entity = new LqStatisticsTechPerformanceEntity
  1743 + {
  1744 + Id = YitIdHelper.NextId().ToString(),
  1745 + StatisticsMonth = statisticsMonth,
  1746 + TeacherId = data.TeacherId?.ToString() ?? "",
  1747 + TeacherName = data.TeacherName?.ToString() ?? "",
  1748 + TeacherAccount = data.TeacherAccount?.ToString() ?? "",
  1749 + StoreId = data.StoreId?.ToString() ?? "",
  1750 + StoreName = data.StoreName?.ToString() ?? "",
  1751 + OrderCount = Convert.ToInt32(data.OrderCount ?? 0),
  1752 + TotalPerformance = Convert.ToDecimal(data.TotalPerformance ?? 0),
  1753 + LaborCost = Convert.ToDecimal(data.LaborCost ?? 0),
  1754 + ProjectCount = Convert.ToDecimal(data.ProjectCount ?? 0),
  1755 + LastOrderDate = data.LastOrderDate as DateTime?,
  1756 + FirstOrderDate = data.FirstOrderDate as DateTime?,
  1757 + CreateTime = DateTime.Now
  1758 + };
  1759 + entities.Add(entity);
  1760 + _logger.LogInformation($"成功转换实体: TeacherId={entity.TeacherId}, TotalPerformance={entity.TotalPerformance}");
  1761 + }
  1762 + catch (Exception ex)
  1763 + {
  1764 + _logger.LogError($"转换实体失败: TeacherId={data.TeacherId}, Error={ex.Message}");
  1765 + }
  1766 + }
  1767 +
  1768 + _logger.LogInformation($"准备插入 {entities.Count} 条实体数据");
  1769 +
  1770 + // 使用事务确保数据一致性
  1771 + var result = await _db.Ado.UseTranAsync(async () =>
  1772 + {
  1773 + try
  1774 + {
  1775 + // 先删除该月份的历史数据
  1776 + var deleteResult = await _db.Deleteable<LqStatisticsTechPerformanceEntity>()
  1777 + .Where(x => x.StatisticsMonth == statisticsMonth)
  1778 + .ExecuteCommandAsync();
  1779 + _logger.LogInformation($"删除历史数据结果: {deleteResult}");
  1780 +
  1781 + // 批量插入新数据
  1782 + var insertResult = await _db.Insertable(entities).ExecuteCommandAsync();
  1783 + _logger.LogInformation($"插入新数据结果: {insertResult}");
  1784 + return insertResult;
  1785 + }
  1786 + catch (Exception ex)
  1787 + {
  1788 + _logger.LogError($"事务执行失败: {ex.Message}");
  1789 + throw;
  1790 + }
  1791 + });
  1792 +
  1793 + _logger.LogInformation($"事务执行结果: IsSuccess={result.IsSuccess}, Data={result.Data}, ErrorMessage={result.ErrorMessage}");
  1794 + var savedCount = result.IsSuccess ? result.Data : 0;
  1795 + _logger.LogInformation($"成功保存科技部开单业绩统计数据 - 月份: {statisticsMonth}, 记录数: {savedCount}");
  1796 +
  1797 + return new
  1798 + {
  1799 + Success = true,
  1800 + Message = $"成功保存 {savedCount} 条科技部开单业绩统计数据",
  1801 + SavedCount = savedCount,
  1802 + StatisticsMonth = statisticsMonth
  1803 + };
  1804 + }
  1805 + catch (Exception ex)
  1806 + {
  1807 + _logger.LogError(ex, $"保存科技部开单业绩统计数据失败 - 月份: {statisticsMonth}");
  1808 + throw NCCException.Oh($"保存科技部开单业绩统计数据失败: {ex.Message}");
  1809 + }
  1810 + }
  1811 +
  1812 + /// <summary>
  1813 + /// 获取科技部开单业绩统计数据
  1814 + /// </summary>
  1815 + /// <remarks>
  1816 + /// 分页查询科技部开单业绩统计数据
  1817 + ///
  1818 + /// 示例请求:
  1819 + /// ```json
  1820 + /// GET /api/Extend/LqStatistics/get-tech-performance-statistics?PageIndex=1&amp;PageSize=10&amp;StatisticsMonth=202401
  1821 + /// ```
  1822 + /// </remarks>
  1823 + /// <param name="input">查询参数</param>
  1824 + /// <returns>分页数据</returns>
  1825 + /// <response code="200">查询成功</response>
  1826 + /// <response code="400">参数错误</response>
  1827 + /// <response code="500">服务器内部错误</response>
  1828 + [HttpGet("get-tech-performance-statistics")]
  1829 + public async Task<dynamic> GetTechPerformanceStatistics([FromQuery] LqStatisticsTechPerformanceListQueryInput input)
  1830 + {
  1831 + try
  1832 + {
  1833 + var query = _db.Queryable<LqStatisticsTechPerformanceEntity>();
  1834 +
  1835 + // 添加查询条件
  1836 + query = query.WhereIF(!string.IsNullOrEmpty(input.StatisticsMonth), x => x.StatisticsMonth == input.StatisticsMonth);
  1837 + query = query.WhereIF(!string.IsNullOrEmpty(input.TeacherId), x => x.TeacherId == input.TeacherId);
  1838 + query = query.WhereIF(!string.IsNullOrEmpty(input.TeacherName), x => x.TeacherName.Contains(input.TeacherName));
  1839 + query = query.WhereIF(!string.IsNullOrEmpty(input.StoreId), x => x.StoreId == input.StoreId);
  1840 + query = query.WhereIF(!string.IsNullOrEmpty(input.StoreName), x => x.StoreName.Contains(input.StoreName));
  1841 +
  1842 + // 按业绩降序排序
  1843 + query = query.OrderBy(x => x.TotalPerformance, OrderByType.Desc);
  1844 +
  1845 + // 分页查询
  1846 + var result = await query.ToPagedListAsync(input.currentPage, input.pageSize);
  1847 +
  1848 + return new
  1849 + {
  1850 + Success = true,
  1851 + Data = new
  1852 + {
  1853 + Records = result.list.Select(x => new LqStatisticsTechPerformanceListOutput
  1854 + {
  1855 + Id = x.Id,
  1856 + StatisticsMonth = x.StatisticsMonth,
  1857 + TeacherId = x.TeacherId,
  1858 + TeacherName = x.TeacherName,
  1859 + TeacherAccount = x.TeacherAccount,
  1860 + StoreId = x.StoreId,
  1861 + StoreName = x.StoreName,
  1862 + OrderCount = x.OrderCount,
  1863 + TotalPerformance = x.TotalPerformance,
  1864 + LaborCost = x.LaborCost,
  1865 + ProjectCount = x.ProjectCount,
  1866 + LastOrderDate = x.LastOrderDate,
  1867 + FirstOrderDate = x.FirstOrderDate,
  1868 + CreateTime = x.CreateTime
  1869 + }).ToList(),
  1870 + Total = result.pagination.Total,
  1871 + PageIndex = input.currentPage,
  1872 + PageSize = input.pageSize
  1873 + }
  1874 + };
  1875 + }
  1876 + catch (Exception ex)
  1877 + {
  1878 + _logger.LogError(ex, "查询科技部开单业绩统计数据失败");
  1879 + throw NCCException.Oh($"查询科技部开单业绩统计数据失败: {ex.Message}");
  1880 + }
  1881 + }
  1882 +
  1883 + #endregion
  1884 +
1637 1885 /// <summary>
1638 1886 /// 部门信息
1639 1887 /// </summary>
... ... @@ -1654,5 +1902,6 @@ namespace NCC.Extend.LqStatistics
1654 1902 /// </summary>
1655 1903 public string ParentId { get; set; }
1656 1904 }
  1905 +
1657 1906 }
1658 1907 }
... ...
netcore/src/Modularity/Extend/NCC.Extend/LqTkjlbService.cs
... ... @@ -182,6 +182,7 @@ namespace NCC.Extend.LqTkjlb
182 182 MemberInfo.Sjh = input.customerPhone; // 设置手机号
183 183 MemberInfo.Khlx = "线索";
184 184 MemberInfo.Dah = "GK" + DateTime.Now.ToString("yyyyMMddHHmmss");
  185 + MemberInfo.Gsmd = eventUserInfo.StoreId;
185 186 var memberResult = await _db.Insertable(MemberInfo).IgnoreColumns(ignoreNullColumn: true).ExecuteCommandAsync();
186 187 if (!(memberResult > 0))
187 188 {
... ...
netcore/src/Modularity/Extend/NCC.Extend/Utils/LqKdKdjlbStringGenerator.cs
... ... @@ -47,35 +47,35 @@ namespace NCC.Extend.Utils
47 47 // 健康师:王维
48 48 var healthTeachers = GetHealthTeachers(entity.lqKdJksyjList);
49 49 sb.AppendLine($"⏩健康师:{healthTeachers}");
50   -
  50 +
51 51 // 活动方案:532工程
52 52 sb.AppendLine($"⏩活动方案:{entity.pxxx ?? "无"}");
53   -
  53 +
54 54 // 跟单配合:王经理 竹主任 陈思思老师
55 55 var techTeachers = GetTechTeachers(entity.lqKdKjbsyjList);
56 56 sb.AppendLine($"⏩跟单配合:{techTeachers}");
57   -
  57 +
58 58 // 业绩:4800
59 59 sb.AppendLine($"⏩业绩:{entity.zdyj}");
60   -
  60 +
61 61 // 实付:4800
62 62 sb.AppendLine($"⏩实付:{entity.sfyj}");
63   -
  63 +
64 64 // 欠款:
65 65 sb.AppendLine($"⏩欠款: {entity.qk}");
66   -
  66 +
67 67 // 抵扣:
68 68 sb.AppendLine($"⏩抵扣:{entity.ckmx ?? "无"}");
69   -
  69 +
70 70 // 来源:售后
71 71 sb.AppendLine($"⏩来源:{entity.khly ?? "无"}");
72   -
  72 +
73 73 // 是否属于升单:
74 74 sb.AppendLine($"⏩是否属于升单:{entity.sfskdd ?? "无"}");
75   -
  75 +
76 76 // 简介:高姐是我们的老客,今天邀约到犀浦店做532,维维全程陪同,陈思思老师在操作过程中给姐姐分享企业文化,找到顾客需求、邀请王经理 竹主任 给到顾客福利、顾客爽快成交,私密档案已了解到70%,感谢顾客的信任与支持 ,王经理 竹主任 陈老师辛苦了[玫瑰]维维真棒[强]龙城国际店加油!我们还在努力中!家人们给我们打气加油👏👏👏👏等待我们的捷报👍👍
77 77 sb.AppendLine($"⏩简介:{entity.jj ?? "无"}");
78   -
  78 +
79 79 return sb.ToString();
80 80 }
81 81  
... ... @@ -94,9 +94,9 @@ namespace NCC.Extend.Utils
94 94 try
95 95 {
96 96 var store = _db.Queryable<LqMdxxEntity>()
97   - .Where(x => x.Mdbm == storeCode)
  97 + .Where(x => x.Id == storeCode)
98 98 .First();
99   -
  99 +
100 100 return store?.Dm ?? storeCode;
101 101 }
102 102 catch
... ... @@ -122,7 +122,7 @@ namespace NCC.Extend.Utils
122 122 var department = _db.Queryable<LqYcsdJsjEntity>()
123 123 .Where(x => x.Id == departmentCode)
124 124 .First();
125   -
  125 +
126 126 return department?.Jsj ?? departmentCode;
127 127 }
128 128 catch
... ... @@ -216,7 +216,7 @@ namespace NCC.Extend.Utils
216 216 var customer = _db.Queryable<LqKhxxEntity>()
217 217 .Where(x => x.Id == customerId)
218 218 .First();
219   -
  219 +
220 220 return customer?.Khmc ?? "无";
221 221 }
222 222 catch
... ... @@ -242,7 +242,7 @@ namespace NCC.Extend.Utils
242 242 var user = _db.Queryable<UserEntity>()
243 243 .Where(x => x.Account == account && x.DeleteMark == null)
244 244 .First();
245   -
  245 +
246 246 return user?.RealName ?? string.Empty;
247 247 }
248 248 catch
... ...