Commit cf15f468b90e4ba73c2420d2d1b74f8309c7cacc

Authored by 李宇
2 parents 140ec06a 5b462535

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

Showing 94 changed files with 9044 additions and 219 deletions
antis-ncc-admin/.env.development
... ... @@ -2,6 +2,6 @@
2 2  
3 3 VUE_CLI_BABEL_TRANSPILE_MODULES = true
4 4 # VUE_APP_BASE_API = 'http://lvqian.antissoft.com'
5   -VUE_APP_BASE_API = 'http://erp_test.lvqianmeiye.com'
6   -# VUE_APP_BASE_API = 'http://localhost:2011'
  5 +# VUE_APP_BASE_API = 'http://erp_test.lvqianmeiye.com'
  6 +VUE_APP_BASE_API = 'http://localhost:2011'
7 7 VUE_APP_BASE_WSS = 'ws://192.168.110.45:2011/websocket'
... ...
antis-ncc-admin/src/api/extend/lqInventory.js 0 → 100644
  1 +import request from '@/utils/request'
  2 +
  3 +// ========== 库存管理接口 ==========
  4 +
  5 +// 创建库存
  6 +export function createInventory(data) {
  7 + return request({
  8 + url: '/api/Extend/LqInventory/Create',
  9 + method: 'post',
  10 + data
  11 + })
  12 +}
  13 +
  14 +// 更新库存
  15 +export function updateInventory(data) {
  16 + return request({
  17 + url: '/api/Extend/LqInventory/Update',
  18 + method: 'put',
  19 + data
  20 + })
  21 +}
  22 +
  23 +// 获取库存列表
  24 +export function getInventoryList(params) {
  25 + return request({
  26 + url: '/api/Extend/LqInventory/GetList',
  27 + method: 'get',
  28 + data: params
  29 + })
  30 +}
  31 +
  32 +// 获取库存详情
  33 +export function getInventoryInfo(id) {
  34 + return request({
  35 + url: '/api/Extend/LqInventory/GetInfo',
  36 + method: 'get',
  37 + data: { id }
  38 + })
  39 +}
  40 +
  41 +// ========== 库存使用记录接口 ==========
  42 +
  43 +// 添加库存使用记录
  44 +export function createInventoryUsage(data) {
  45 + return request({
  46 + url: '/api/Extend/LqInventoryUsage/Create',
  47 + method: 'post',
  48 + data
  49 + })
  50 +}
  51 +
  52 +// 作废库存使用记录
  53 +export function cancelInventoryUsage(id, remarks) {
  54 + return request({
  55 + url: '/api/Extend/LqInventoryUsage/Cancel',
  56 + method: 'put',
  57 + data: { id, remarks }
  58 + })
  59 +}
  60 +
  61 +// 获取使用记录列表
  62 +export function getInventoryUsageList(params) {
  63 + return request({
  64 + url: '/api/Extend/LqInventoryUsage/GetList',
  65 + method: 'get',
  66 + data: params
  67 + })
  68 +}
  69 +
  70 +// 获取产品使用统计
  71 +export function getProductUsageStatistics(data) {
  72 + return request({
  73 + url: '/api/Extend/LqInventoryUsage/GetProductUsageStatistics',
  74 + method: 'post',
  75 + data
  76 + })
  77 +}
  78 +
  79 +// 获取门店使用统计
  80 +export function getStoreUsageStatistics(data) {
  81 + return request({
  82 + url: '/api/Extend/LqInventoryUsage/GetStoreUsageStatistics',
  83 + method: 'post',
  84 + data
  85 + })
  86 +}
  87 +
  88 +// 获取使用趋势统计
  89 +export function getUsageTrendStatistics(data) {
  90 + return request({
  91 + url: '/api/Extend/LqInventoryUsage/GetUsageTrendStatistics',
  92 + method: 'post',
  93 + data
  94 + })
  95 +}
  96 +
  97 +// 获取产品使用排行榜
  98 +export function getProductUsageRanking(data) {
  99 + return request({
  100 + url: '/api/Extend/LqInventoryUsage/GetProductUsageRanking',
  101 + method: 'post',
  102 + data
  103 + })
  104 +}
  105 +
... ...
antis-ncc-admin/src/api/extend/lqStudyClass.js 0 → 100644
  1 +import request from '@/utils/request'
  2 +
  3 +// 创建学习班级并添加学员
  4 +export function createClassWithStudents(data) {
  5 + return request({
  6 + url: '/api/Extend/LqStudyClass/CreateClassWithStudents',
  7 + method: 'post',
  8 + data
  9 + })
  10 +}
  11 +
  12 +// 向现有班级添加学员
  13 +export function addStudentsToClass(data) {
  14 + return request({
  15 + url: '/api/Extend/LqStudyClass/AddStudentsToClass',
  16 + method: 'post',
  17 + data
  18 + })
  19 +}
  20 +
  21 +// 获取所有班级列表
  22 +export function getClassList(params) {
  23 + return request({
  24 + url: '/api/Extend/LqStudyClass/GetClassList',
  25 + method: 'get',
  26 + data: params
  27 + })
  28 +}
  29 +
  30 +// 获取班级下所有学员信息
  31 +export function getStudentListByClassId(params) {
  32 + return request({
  33 + url: '/api/Extend/LqStudyClass/GetStudentListByClassId',
  34 + method: 'get',
  35 + data: params
  36 + })
  37 +}
  38 +
  39 +// 添加学习记录
  40 +export function addStudyRecord(data) {
  41 + return request({
  42 + url: '/api/Extend/LqStudyClass/AddStudyRecord',
  43 + method: 'post',
  44 + data
  45 + })
  46 +}
  47 +
  48 +// 获取学习记录列表
  49 +export function getStudyRecordList(params) {
  50 + return request({
  51 + url: '/api/Extend/LqStudyClass/GetStudyRecordList',
  52 + method: 'get',
  53 + data: params
  54 + })
  55 +}
  56 +
  57 +// 作废学习记录
  58 +export function cancelStudyRecord(id) {
  59 + return request({
  60 + url: '/api/Extend/LqStudyClass/CancelStudyRecord',
  61 + method: 'post',
  62 + data: id
  63 + })
  64 +}
  65 +
... ...
antis-ncc-admin/src/router/modules/base.js
... ... @@ -76,6 +76,17 @@ const baseRouter = [{
76 76 icon: 'icon-ym icon-ym-s-data',
77 77 }
78 78 },
  79 + {
  80 + path: '/lqInventory',
  81 + component: (resolve) => require(['@/views/lqInventory'], resolve),
  82 + name: 'lqInventory',
  83 + meta: {
  84 + title: 'lqInventory',
  85 + affix: false,
  86 + zhTitle: '库存管理',
  87 + icon: 'icon-ym icon-ym-box',
  88 + }
  89 + },
79 90 {
80 91 path: '/salaryCalculation',
81 92 component: (resolve) => require(['@/views/salaryCalculation/index'], resolve),
... ...
antis-ncc-admin/src/views/lqInventory/AddUsageRecordForm.vue 0 → 100644
  1 +<template>
  2 + <el-dialog title="添加库存使用记录" :visible.sync="visible" width="600px" @close="closeDialog">
  3 + <el-form ref="form" :model="form" :rules="rules" label-width="100px">
  4 + <el-row :gutter="20">
  5 + <el-col :span="12">
  6 + <el-form-item label="产品" prop="productId">
  7 + <el-select v-model="form.productId" placeholder="请选择产品" style="width: 100%"
  8 + @change="onProductChange">
  9 + <el-option v-for="product in productList" :key="product.id" :label="product.productName"
  10 + :value="product.id">
  11 + <span style="float: left">{{ product.productName }}</span>
  12 + <span style="float: right; color: #8492a6; font-size: 13px">{{ product.productCategory
  13 + }}</span>
  14 + </el-option>
  15 + </el-select>
  16 + </el-form-item>
  17 + </el-col>
  18 + <el-col :span="12">
  19 + <el-form-item label="使用门店" prop="storeId">
  20 + <userSelect v-model="form.storeId" placeholder="请选择使用门店" @change="onStoreChange" />
  21 + </el-form-item>
  22 + </el-col>
  23 + </el-row>
  24 +
  25 + <el-row :gutter="20">
  26 + <el-col :span="12">
  27 + <el-form-item label="使用数量" prop="usageQuantity">
  28 + <el-input-number v-model="form.usageQuantity" :min="1" style="width: 100%"
  29 + placeholder="请输入使用数量" />
  30 + </el-form-item>
  31 + </el-col>
  32 + <el-col :span="12">
  33 + <el-form-item label="使用时间" prop="usageTime">
  34 + <el-date-picker v-model="form.usageTime" type="date" placeholder="选择使用时间"
  35 + value-format="yyyy-MM-dd" style="width: 100%" />
  36 + </el-form-item>
  37 + </el-col>
  38 + </el-row>
  39 +
  40 + <el-form-item label="关联消费ID">
  41 + <el-input v-model="form.relatedConsumeId" placeholder="请输入关联消费ID(可选)" />
  42 + </el-form-item>
  43 +
  44 + <el-form-item label="备注">
  45 + <el-input v-model="form.remark" type="textarea" :rows="3" placeholder="请输入备注信息" />
  46 + </el-form-item>
  47 +
  48 + <!-- 产品信息显示 -->
  49 + <div v-if="selectedProduct" class="product-info">
  50 + <el-divider content-position="left">产品信息</el-divider>
  51 + <el-row :gutter="20">
  52 + <el-col :span="8">
  53 + <div class="info-item">
  54 + <label>产品分类:</label>
  55 + <span>{{ selectedProduct.productCategory }}</span>
  56 + </div>
  57 + </el-col>
  58 + <el-col :span="8">
  59 + <div class="info-item">
  60 + <label>单价:</label>
  61 + <span class="price">{{ formatMoney(selectedProduct.price) }}</span>
  62 + </div>
  63 + </el-col>
  64 + <el-col :span="8">
  65 + <div class="info-item">
  66 + <label>当前库存:</label>
  67 + <span :class="selectedProduct.quantity <= 10 ? 'text-danger' : ''">{{
  68 + selectedProduct.quantity }}</span>
  69 + </div>
  70 + </el-col>
  71 + </el-row>
  72 + </div>
  73 + </el-form>
  74 +
  75 + <div slot="footer" class="dialog-footer">
  76 + <el-button @click="closeDialog">取消</el-button>
  77 + <el-button type="primary" @click="submitForm" :loading="submitLoading">确定</el-button>
  78 + </div>
  79 + </el-dialog>
  80 +</template>
  81 +
  82 +<script>
  83 +import { createInventoryUsage, getInventoryList } from '@/api/extend/lqInventory'
  84 +
  85 +export default {
  86 + name: 'AddUsageRecordForm',
  87 + data() {
  88 + return {
  89 + visible: false,
  90 + submitLoading: false,
  91 + productId: '', // 特定产品ID
  92 + productName: '', // 特定产品名称
  93 + productList: [], // 产品列表
  94 + selectedProduct: null, // 选中的产品
  95 + form: {
  96 + productId: '',
  97 + storeId: '',
  98 + usageQuantity: 1,
  99 + usageTime: '',
  100 + relatedConsumeId: '',
  101 + remark: ''
  102 + },
  103 + rules: {
  104 + productId: [
  105 + { required: true, message: '请选择产品', trigger: 'change' }
  106 + ],
  107 + storeId: [
  108 + { required: true, message: '请选择使用门店', trigger: 'change' }
  109 + ],
  110 + usageQuantity: [
  111 + { required: true, message: '请输入使用数量', trigger: 'blur' }
  112 + ],
  113 + usageTime: [
  114 + { required: true, message: '请选择使用时间', trigger: 'change' }
  115 + ]
  116 + }
  117 + }
  118 + },
  119 + methods: {
  120 + init(productId = '', productName = '') {
  121 + this.visible = true
  122 + this.productId = productId
  123 + this.productName = productName
  124 + this.getProductList()
  125 + this.resetForm()
  126 + },
  127 +
  128 + // 获取产品列表
  129 + getProductList() {
  130 + const params = {
  131 + currentPage: 1,
  132 + pageSize: 1000, // 获取所有产品
  133 + isEffective: 1 // 只获取有效产品
  134 + }
  135 +
  136 + getInventoryList(params).then(response => {
  137 + if (response.code === 200) {
  138 + this.productList = response.data.list || []
  139 + // 如果指定了产品ID,自动选中
  140 + if (this.productId) {
  141 + this.form.productId = this.productId
  142 + this.onProductChange(this.productId)
  143 + }
  144 + } else {
  145 + this.$message.error(response.msg || '获取产品列表失败')
  146 + }
  147 + })
  148 + },
  149 +
  150 + // 产品选择变化
  151 + onProductChange(productId) {
  152 + this.selectedProduct = this.productList.find(product => product.id === productId)
  153 + },
  154 +
  155 + // 门店选择变化
  156 + onStoreChange(ids, users) {
  157 + // userSelect组件的回调处理
  158 + },
  159 +
  160 + resetForm() {
  161 + this.form = {
  162 + productId: this.productId || '',
  163 + storeId: '',
  164 + usageQuantity: 1,
  165 + usageTime: '',
  166 + relatedConsumeId: '',
  167 + remark: ''
  168 + }
  169 + this.selectedProduct = null
  170 + this.$nextTick(() => {
  171 + if (this.$refs.form) {
  172 + this.$refs.form.clearValidate()
  173 + }
  174 + })
  175 + },
  176 +
  177 + // 提交表单
  178 + submitForm() {
  179 + this.$refs.form.validate((valid) => {
  180 + if (valid) {
  181 + // 检查库存数量
  182 + if (this.selectedProduct && this.form.usageQuantity > this.selectedProduct.quantity) {
  183 + this.$message.error(`库存不足,当前库存:${this.selectedProduct.quantity},需要数量:${this.form.usageQuantity}`)
  184 + return
  185 + }
  186 +
  187 + this.submitLoading = true
  188 + createInventoryUsage(this.form).then(response => {
  189 + if (response.code === 200) {
  190 + this.$message.success('添加成功')
  191 + this.closeDialog()
  192 + this.$emit('refreshDataList')
  193 + } else {
  194 + this.$message.error(response.msg || '添加失败')
  195 + }
  196 + this.submitLoading = false
  197 + }).catch(() => {
  198 + this.submitLoading = false
  199 + })
  200 + }
  201 + })
  202 + },
  203 +
  204 + // 格式化金额
  205 + formatMoney(value) {
  206 + if (value === null || value === undefined || value === '') {
  207 + return '0.00'
  208 + }
  209 + return Number(value).toFixed(2)
  210 + },
  211 +
  212 + // 关闭弹窗
  213 + closeDialog() {
  214 + this.visible = false
  215 + this.resetForm()
  216 + }
  217 + }
  218 +}
  219 +</script>
  220 +
  221 +<style scoped>
  222 +.dialog-footer {
  223 + text-align: right;
  224 +}
  225 +
  226 +.product-info {
  227 + margin-top: 20px;
  228 + padding: 15px;
  229 + background: #f5f7fa;
  230 + border-radius: 4px;
  231 +}
  232 +
  233 +.info-item {
  234 + margin-bottom: 10px;
  235 + display: flex;
  236 + align-items: center;
  237 +}
  238 +
  239 +.info-item label {
  240 + font-weight: bold;
  241 + color: #606266;
  242 + min-width: 80px;
  243 + margin-right: 10px;
  244 +}
  245 +
  246 +.info-item span {
  247 + color: #303133;
  248 +}
  249 +
  250 +.price {
  251 + color: #e6a23c;
  252 + font-weight: bold;
  253 +}
  254 +
  255 +.text-danger {
  256 + color: #f56c6c;
  257 + font-weight: bold;
  258 +}
  259 +</style>
  260 +
... ...
antis-ncc-admin/src/views/lqInventory/InventoryForm.vue 0 → 100644
  1 +<template>
  2 + <el-dialog :title="isEdit ? '编辑库存' : '添加库存'" :visible.sync="visible" width="600px" @close="closeDialog">
  3 + <el-form ref="form" :model="form" :rules="rules" label-width="100px">
  4 + <el-row :gutter="20">
  5 + <el-col :span="12">
  6 + <el-form-item label="产品名称" prop="productName">
  7 + <el-input v-model="form.productName" placeholder="请输入产品名称" />
  8 + </el-form-item>
  9 + </el-col>
  10 + <el-col :span="12">
  11 + <el-form-item label="产品分类" prop="productCategory">
  12 + <el-input v-model="form.productCategory" placeholder="请输入产品分类" />
  13 + </el-form-item>
  14 + </el-col>
  15 + </el-row>
  16 +
  17 + <el-row :gutter="20">
  18 + <el-col :span="12">
  19 + <el-form-item label="单价" prop="price">
  20 + <el-input-number v-model="form.price" :min="0" :precision="2" style="width: 100%"
  21 + placeholder="请输入单价" />
  22 + </el-form-item>
  23 + </el-col>
  24 + <el-col :span="12">
  25 + <el-form-item label="库存数量" prop="quantity">
  26 + <el-input-number v-model="form.quantity" :min="0" style="width: 100%" placeholder="请输入库存数量" />
  27 + </el-form-item>
  28 + </el-col>
  29 + </el-row>
  30 +
  31 + <el-row :gutter="20">
  32 + <el-col :span="12">
  33 + <el-form-item label="标准单位" prop="standardUnit">
  34 + <el-input v-model="form.standardUnit" placeholder="请输入标准单位" />
  35 + </el-form-item>
  36 + </el-col>
  37 + <el-col :span="12">
  38 + <el-form-item label="负责部门" prop="departmentId">
  39 + <el-select v-model="form.departmentId" placeholder="请选择负责部门" style="width: 100%" clearable>
  40 + <el-option v-for="dept in departmentList" :key="dept.id" :label="dept.name"
  41 + :value="dept.id">
  42 + </el-option>
  43 + </el-select>
  44 + </el-form-item>
  45 + </el-col>
  46 + </el-row>
  47 +
  48 + <el-form-item label="备注">
  49 + <el-input v-model="form.remark" type="textarea" :rows="3" placeholder="请输入备注信息" />
  50 + </el-form-item>
  51 + </el-form>
  52 +
  53 + <div slot="footer" class="dialog-footer">
  54 + <el-button @click="closeDialog">取消</el-button>
  55 + <el-button type="primary" @click="submitForm" :loading="submitLoading">确定</el-button>
  56 + </div>
  57 + </el-dialog>
  58 +</template>
  59 +
  60 +<script>
  61 +import { createInventory, updateInventory, getInventoryInfo } from '@/api/extend/lqInventory'
  62 +import { getUserList } from '@/api/permission/user'
  63 +
  64 +export default {
  65 + name: 'InventoryForm',
  66 + data() {
  67 + return {
  68 + visible: false,
  69 + submitLoading: false,
  70 + isEdit: false,
  71 + departmentList: [], // 部门列表
  72 + form: {
  73 + id: '',
  74 + productName: '',
  75 + productCategory: '',
  76 + price: 0,
  77 + quantity: 0,
  78 + standardUnit: '',
  79 + departmentId: '',
  80 + departmentName: '',
  81 + remark: ''
  82 + },
  83 + rules: {
  84 + productName: [
  85 + { required: true, message: '请输入产品名称', trigger: 'blur' }
  86 + ],
  87 + productCategory: [
  88 + { required: true, message: '请输入产品分类', trigger: 'blur' }
  89 + ],
  90 + price: [
  91 + { required: true, message: '请输入单价', trigger: 'blur' }
  92 + ],
  93 + quantity: [
  94 + { required: true, message: '请输入库存数量', trigger: 'blur' }
  95 + ],
  96 + standardUnit: [
  97 + { required: true, message: '请输入标准单位', trigger: 'blur' }
  98 + ],
  99 + departmentId: [
  100 + { required: true, message: '请选择负责部门', trigger: 'change' }
  101 + ]
  102 + }
  103 + }
  104 + },
  105 + methods: {
  106 + init(id = '') {
  107 + this.visible = true
  108 + this.isEdit = !!id
  109 + this.getDepartmentList()
  110 + if (this.isEdit) {
  111 + this.getInventoryInfo(id)
  112 + } else {
  113 + this.resetForm()
  114 + }
  115 + },
  116 +
  117 + // 获取部门列表
  118 + getDepartmentList() {
  119 + const params = {
  120 + currentPage: 1,
  121 + pageSize: 1000, // 获取所有部门
  122 + enabledMark: 1 // 只获取启用的部门
  123 + }
  124 +
  125 + getUserList(params).then(response => {
  126 + if (response.code === 200) {
  127 + // 将用户列表转换为部门列表格式
  128 + this.departmentList = response.data.list.map(user => ({
  129 + id: user.id,
  130 + name: user.realName
  131 + }))
  132 + } else {
  133 + this.$message.error(response.msg || '获取部门列表失败')
  134 + }
  135 + }).catch(() => {
  136 + this.$message.error('获取部门列表失败')
  137 + })
  138 + },
  139 +
  140 + // 获取库存详情
  141 + getInventoryInfo(id) {
  142 + getInventoryInfo(id).then(response => {
  143 + if (response.code === 200) {
  144 + this.form = {
  145 + id: response.data.id,
  146 + productName: response.data.productName,
  147 + productCategory: response.data.productCategory,
  148 + price: response.data.price,
  149 + quantity: response.data.quantity,
  150 + standardUnit: response.data.standardUnit,
  151 + departmentId: response.data.departmentId,
  152 + departmentName: response.data.departmentName,
  153 + remark: response.data.remark || ''
  154 + }
  155 + } else {
  156 + this.$message.error(response.msg || '获取库存详情失败')
  157 + }
  158 + })
  159 + },
  160 +
  161 +
  162 + resetForm() {
  163 + this.form = {
  164 + id: '',
  165 + productName: '',
  166 + productCategory: '',
  167 + price: 0,
  168 + quantity: 0,
  169 + standardUnit: '',
  170 + departmentId: '',
  171 + departmentName: '',
  172 + remark: ''
  173 + }
  174 + this.$nextTick(() => {
  175 + if (this.$refs.form) {
  176 + this.$refs.form.clearValidate()
  177 + }
  178 + })
  179 + },
  180 +
  181 + // 提交表单
  182 + submitForm() {
  183 + this.$refs.form.validate((valid) => {
  184 + if (valid) {
  185 + this.submitLoading = true
  186 + const apiMethod = this.isEdit ? updateInventory : createInventory
  187 + apiMethod(this.form).then(response => {
  188 + if (response.code === 200) {
  189 + this.$message.success(this.isEdit ? '更新成功' : '创建成功')
  190 + this.closeDialog()
  191 + this.$emit('refreshDataList')
  192 + } else {
  193 + this.$message.error(response.msg || (this.isEdit ? '更新失败' : '创建失败'))
  194 + }
  195 + this.submitLoading = false
  196 + }).catch(() => {
  197 + this.submitLoading = false
  198 + })
  199 + }
  200 + })
  201 + },
  202 +
  203 + // 关闭弹窗
  204 + closeDialog() {
  205 + this.visible = false
  206 + this.resetForm()
  207 + }
  208 + }
  209 +}
  210 +</script>
  211 +
  212 +<style scoped>
  213 +.dialog-footer {
  214 + text-align: right;
  215 +}
  216 +</style>
... ...
antis-ncc-admin/src/views/lqInventory/InventoryInfoDialog.vue 0 → 100644
  1 +<template>
  2 + <el-dialog title="库存详情" :visible.sync="visible" width="800px" @close="closeDialog">
  3 + <div class="inventory-info-container">
  4 + <el-row :gutter="20">
  5 + <el-col :span="12">
  6 + <div class="info-item">
  7 + <label>产品名称:</label>
  8 + <span>{{ inventoryInfo.productName || '无' }}</span>
  9 + </div>
  10 + </el-col>
  11 + <el-col :span="12">
  12 + <div class="info-item">
  13 + <label>产品分类:</label>
  14 + <span>{{ inventoryInfo.productCategory || '无' }}</span>
  15 + </div>
  16 + </el-col>
  17 + </el-row>
  18 +
  19 + <el-row :gutter="20">
  20 + <el-col :span="12">
  21 + <div class="info-item">
  22 + <label>单价:</label>
  23 + <span class="price">{{ formatMoney(inventoryInfo.price) }}</span>
  24 + </div>
  25 + </el-col>
  26 + <el-col :span="12">
  27 + <div class="info-item">
  28 + <label>库存数量:</label>
  29 + <span :class="inventoryInfo.quantity <= 10 ? 'text-danger' : ''">{{ inventoryInfo.quantity || 0
  30 + }}</span>
  31 + </div>
  32 + </el-col>
  33 + </el-row>
  34 +
  35 + <el-row :gutter="20">
  36 + <el-col :span="12">
  37 + <div class="info-item">
  38 + <label>标准单位:</label>
  39 + <span>{{ inventoryInfo.standardUnit || '无' }}</span>
  40 + </div>
  41 + </el-col>
  42 + <el-col :span="12">
  43 + <div class="info-item">
  44 + <label>总价值:</label>
  45 + <span class="price">{{ formatMoney(inventoryInfo.totalValue) }}</span>
  46 + </div>
  47 + </el-col>
  48 + </el-row>
  49 +
  50 + <el-row :gutter="20">
  51 + <el-col :span="12">
  52 + <div class="info-item">
  53 + <label>负责部门:</label>
  54 + <span>{{ inventoryInfo.departmentName || '无' }}</span>
  55 + </div>
  56 + </el-col>
  57 + <el-col :span="12">
  58 + <div class="info-item">
  59 + <label>状态:</label>
  60 + <el-tag :type="inventoryInfo.isEffective === 1 ? 'success' : 'danger'">
  61 + {{ inventoryInfo.isEffective === 1 ? '有效' : '无效' }}
  62 + </el-tag>
  63 + </div>
  64 + </el-col>
  65 + </el-row>
  66 +
  67 + <el-row :gutter="20">
  68 + <el-col :span="12">
  69 + <div class="info-item">
  70 + <label>创建人:</label>
  71 + <span>{{ inventoryInfo.createUserName || '无' }}</span>
  72 + </div>
  73 + </el-col>
  74 + <el-col :span="12">
  75 + <div class="info-item">
  76 + <label>创建时间:</label>
  77 + <span>{{ inventoryInfo.createTime | dateTimeFormat }}</span>
  78 + </div>
  79 + </el-col>
  80 + </el-row>
  81 +
  82 + <el-row :gutter="20" v-if="inventoryInfo.updateTime">
  83 + <el-col :span="12">
  84 + <div class="info-item">
  85 + <label>更新人:</label>
  86 + <span>{{ inventoryInfo.updateUserName || '无' }}</span>
  87 + </div>
  88 + </el-col>
  89 + <el-col :span="12">
  90 + <div class="info-item">
  91 + <label>更新时间:</label>
  92 + <span>{{ inventoryInfo.updateTime | dateTimeFormat }}</span>
  93 + </div>
  94 + </el-col>
  95 + </el-row>
  96 +
  97 + <el-row v-if="inventoryInfo.remark">
  98 + <el-col :span="24">
  99 + <div class="info-item">
  100 + <label>备注:</label>
  101 + <span>{{ inventoryInfo.remark }}</span>
  102 + </div>
  103 + </el-col>
  104 + </el-row>
  105 + </div>
  106 +
  107 + <div slot="footer" class="dialog-footer">
  108 + <el-button @click="closeDialog">关闭</el-button>
  109 + </div>
  110 + </el-dialog>
  111 +</template>
  112 +
  113 +<script>
  114 +import { getInventoryInfo } from '@/api/extend/lqInventory'
  115 +
  116 +export default {
  117 + name: 'InventoryInfoDialog',
  118 + data() {
  119 + return {
  120 + visible: false,
  121 + inventoryInfo: {}
  122 + }
  123 + },
  124 + methods: {
  125 + init(id) {
  126 + this.visible = true
  127 + this.getInventoryInfo(id)
  128 + },
  129 +
  130 + // 获取库存详情
  131 + getInventoryInfo(id) {
  132 + getInventoryInfo(id).then(response => {
  133 + if (response.code === 200) {
  134 + this.inventoryInfo = response.data
  135 + } else {
  136 + this.$message.error(response.msg || '获取库存详情失败')
  137 + }
  138 + })
  139 + },
  140 +
  141 + // 格式化金额
  142 + formatMoney(value) {
  143 + if (value === null || value === undefined || value === '') {
  144 + return '0.00'
  145 + }
  146 + return Number(value).toFixed(2)
  147 + },
  148 +
  149 + // 关闭弹窗
  150 + closeDialog() {
  151 + this.visible = false
  152 + this.inventoryInfo = {}
  153 + }
  154 + }
  155 +}
  156 +</script>
  157 +
  158 +<style scoped>
  159 +.inventory-info-container {
  160 + padding: 20px;
  161 +}
  162 +
  163 +.info-item {
  164 + margin-bottom: 20px;
  165 + display: flex;
  166 + align-items: center;
  167 +}
  168 +
  169 +.info-item label {
  170 + font-weight: bold;
  171 + color: #606266;
  172 + min-width: 100px;
  173 + margin-right: 10px;
  174 +}
  175 +
  176 +.info-item span {
  177 + color: #303133;
  178 +}
  179 +
  180 +.price {
  181 + color: #e6a23c;
  182 + font-weight: bold;
  183 +}
  184 +
  185 +.text-danger {
  186 + color: #f56c6c;
  187 + font-weight: bold;
  188 +}
  189 +
  190 +.dialog-footer {
  191 + text-align: right;
  192 +}
  193 +</style>
  194 +
... ...
antis-ncc-admin/src/views/lqInventory/UsageRecordDialog.vue 0 → 100644
  1 +<template>
  2 + <el-dialog title="库存使用记录管理" :visible.sync="visible" width="1400px" @close="closeDialog">
  3 + <div class="usage-record-container">
  4 + <!-- 搜索区域 -->
  5 + <div class="search-section">
  6 + <el-form :model="query" :inline="true" class="search-form">
  7 + <el-form-item label="产品名称">
  8 + <el-input v-model="query.productName" placeholder="请输入产品名称" clearable size="small" />
  9 + </el-form-item>
  10 + <el-form-item label="产品分类">
  11 + <el-input v-model="query.productCategory" placeholder="请输入产品分类" clearable size="small" />
  12 + </el-form-item>
  13 + <el-form-item label="门店">
  14 + <el-input v-model="query.storeName" placeholder="请输入门店名称" clearable size="small" />
  15 + </el-form-item>
  16 + <el-form-item label="使用时间">
  17 + <el-date-picker v-model="query.usageTimeRange" type="daterange" range-separator="至"
  18 + start-placeholder="开始日期" end-placeholder="结束日期" value-format="yyyy-MM-dd" size="small">
  19 + </el-date-picker>
  20 + </el-form-item>
  21 + <el-form-item>
  22 + <el-button type="primary" size="small" @click="search">搜索</el-button>
  23 + <el-button size="small" @click="reset">重置</el-button>
  24 + <el-button type="success" size="small" icon="el-icon-plus"
  25 + @click="addUsageRecord">添加使用记录</el-button>
  26 + </el-form-item>
  27 + </el-form>
  28 + </div>
  29 +
  30 + <!-- 使用记录列表 -->
  31 + <div class="table-section">
  32 + <el-table :data="usageList" v-loading="loading" border stripe style="width: 100%">
  33 + <el-table-column prop="productName" label="产品名称" width="150" fixed="left" />
  34 + <el-table-column prop="productCategory" label="产品分类" width="120" />
  35 + <el-table-column prop="productPrice" label="单价" width="100" align="right">
  36 + <template slot-scope="scope">
  37 + {{ formatMoney(scope.row.productPrice) }}
  38 + </template>
  39 + </el-table-column>
  40 + <el-table-column prop="usageQuantity" label="使用数量" width="100" align="right" />
  41 + <el-table-column prop="storeName" label="使用门店" width="120" />
  42 + <el-table-column prop="usageTime" label="使用时间" width="120">
  43 + <template slot-scope="scope">
  44 + {{ scope.row.usageTime | dateFormat }}
  45 + </template>
  46 + </el-table-column>
  47 + <el-table-column prop="relatedConsumeId" label="关联消费ID" width="120" />
  48 + <el-table-column prop="createUserName" label="创建人" width="100" />
  49 + <el-table-column prop="createTime" label="创建时间" width="160">
  50 + <template slot-scope="scope">
  51 + {{ scope.row.createTime | dateTimeFormat }}
  52 + </template>
  53 + </el-table-column>
  54 + <el-table-column prop="isEffective" label="状态" width="80" align="center">
  55 + <template slot-scope="scope">
  56 + <el-tag :type="scope.row.isEffective === 1 ? 'success' : 'danger'" size="small">
  57 + {{ scope.row.isEffective === 1 ? '有效' : '无效' }}
  58 + </el-tag>
  59 + </template>
  60 + </el-table-column>
  61 + <el-table-column label="操作" width="120" fixed="right">
  62 + <template slot-scope="scope">
  63 + <el-button v-if="scope.row.isEffective === 1" type="text" size="small"
  64 + @click="cancelUsageRecord(scope.row)">作废</el-button>
  65 + </template>
  66 + </el-table-column>
  67 + </el-table>
  68 +
  69 + <!-- 分页 -->
  70 + <div class="pagination-section">
  71 + <el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange"
  72 + :current-page="pagination.pageIndex" :page-sizes="[10, 20, 50, 100]"
  73 + :page-size="pagination.pageSize" layout="total, sizes, prev, pager, next, jumper"
  74 + :total="pagination.total">
  75 + </el-pagination>
  76 + </div>
  77 + </div>
  78 + </div>
  79 +
  80 + <!-- 添加使用记录弹窗 -->
  81 + <AddUsageRecordForm v-if="addUsageRecordVisible" ref="AddUsageRecordForm" @refreshDataList="getUsageList" />
  82 +
  83 + <div slot="footer" class="dialog-footer">
  84 + <el-button @click="closeDialog">关闭</el-button>
  85 + </div>
  86 + </el-dialog>
  87 +</template>
  88 +
  89 +<script>
  90 +import { getInventoryUsageList, cancelInventoryUsage } from '@/api/extend/lqInventory'
  91 +import AddUsageRecordForm from './AddUsageRecordForm'
  92 +
  93 +export default {
  94 + name: 'UsageRecordDialog',
  95 + components: {
  96 + AddUsageRecordForm
  97 + },
  98 + data() {
  99 + return {
  100 + visible: false,
  101 + loading: false,
  102 + productId: '', // 特定产品ID,为空时显示所有
  103 + productName: '', // 特定产品名称
  104 + usageList: [],
  105 + query: {
  106 + productName: '',
  107 + productCategory: '',
  108 + storeName: '',
  109 + usageTimeRange: [],
  110 + productId: '',
  111 + storeId: '',
  112 + relatedConsumeId: '',
  113 + currentPage: 1,
  114 + pageSize: 20
  115 + },
  116 + pagination: {
  117 + pageIndex: 1,
  118 + pageSize: 20,
  119 + total: 0
  120 + },
  121 + addUsageRecordVisible: false
  122 + }
  123 + },
  124 + methods: {
  125 + init(productId = '', productName = '') {
  126 + this.visible = true
  127 + this.productId = productId
  128 + this.productName = productName
  129 + this.query.productId = productId
  130 + if (productName) {
  131 + this.query.productName = productName
  132 + }
  133 + this.getUsageList()
  134 + },
  135 +
  136 + // 获取使用记录列表
  137 + getUsageList() {
  138 + this.loading = true
  139 + const params = {
  140 + ...this.query,
  141 + currentPage: this.pagination.pageIndex,
  142 + pageSize: this.pagination.pageSize
  143 + }
  144 +
  145 + // 处理日期范围
  146 + if (this.query.usageTimeRange && this.query.usageTimeRange.length === 2) {
  147 + params.usageStartTime = this.query.usageTimeRange[0]
  148 + params.usageEndTime = this.query.usageTimeRange[1]
  149 + }
  150 +
  151 + getInventoryUsageList(params).then(response => {
  152 + if (response.code === 200) {
  153 + this.usageList = response.data.list || []
  154 + this.pagination.total = (response.data.pagination && response.data.pagination.total) || 0
  155 + } else {
  156 + this.$message.error(response.msg || '获取使用记录失败')
  157 + }
  158 + this.loading = false
  159 + }).catch(() => {
  160 + this.loading = false
  161 + })
  162 + },
  163 +
  164 + // 搜索
  165 + search() {
  166 + this.pagination.pageIndex = 1
  167 + this.getUsageList()
  168 + },
  169 +
  170 + // 重置
  171 + reset() {
  172 + this.query = {
  173 + productName: this.productName || '',
  174 + productCategory: '',
  175 + storeName: '',
  176 + usageTimeRange: [],
  177 + productId: this.productId,
  178 + storeId: '',
  179 + relatedConsumeId: '',
  180 + currentPage: 1,
  181 + pageSize: 20
  182 + }
  183 + this.pagination.pageIndex = 1
  184 + this.getUsageList()
  185 + },
  186 +
  187 + // 分页大小改变
  188 + handleSizeChange(val) {
  189 + this.pagination.pageSize = val
  190 + this.pagination.pageIndex = 1
  191 + this.getUsageList()
  192 + },
  193 +
  194 + // 当前页改变
  195 + handleCurrentChange(val) {
  196 + this.pagination.pageIndex = val
  197 + this.getUsageList()
  198 + },
  199 +
  200 + // 添加使用记录
  201 + addUsageRecord() {
  202 + this.addUsageRecordVisible = true
  203 + this.$nextTick(() => {
  204 + this.$refs.AddUsageRecordForm.init(this.productId, this.productName)
  205 + })
  206 + },
  207 +
  208 + // 作废使用记录
  209 + cancelUsageRecord(row) {
  210 + this.$confirm('确定要作废这条使用记录吗?作废后库存数量将恢复。', '提示', {
  211 + confirmButtonText: '确定',
  212 + cancelButtonText: '取消',
  213 + type: 'warning'
  214 + }).then(() => {
  215 + cancelInventoryUsage(row.Id).then(response => {
  216 + if (response.code === 200) {
  217 + this.$message.success('作废成功')
  218 + this.getUsageList()
  219 + } else {
  220 + this.$message.error(response.msg || '作废失败')
  221 + }
  222 + })
  223 + })
  224 + },
  225 +
  226 + // 格式化金额
  227 + formatMoney(value) {
  228 + if (value === null || value === undefined || value === '') {
  229 + return '0.00'
  230 + }
  231 + return Number(value).toFixed(2)
  232 + },
  233 +
  234 + // 关闭弹窗
  235 + closeDialog() {
  236 + this.visible = false
  237 + this.usageList = []
  238 + this.query = {
  239 + productName: '',
  240 + productCategory: '',
  241 + storeName: '',
  242 + usageTimeRange: [],
  243 + productId: '',
  244 + storeId: '',
  245 + relatedConsumeId: '',
  246 + currentPage: 1,
  247 + pageSize: 20
  248 + }
  249 + this.pagination = {
  250 + pageIndex: 1,
  251 + pageSize: 20,
  252 + total: 0
  253 + }
  254 + }
  255 + }
  256 +}
  257 +</script>
  258 +
  259 +<style scoped>
  260 +.usage-record-container {
  261 + padding: 20px;
  262 +}
  263 +
  264 +.search-section {
  265 + margin-bottom: 20px;
  266 + padding: 15px;
  267 + background: #f5f7fa;
  268 + border-radius: 4px;
  269 +}
  270 +
  271 +.search-form .el-form-item {
  272 + margin-bottom: 10px;
  273 +}
  274 +
  275 +.table-section {
  276 + margin-bottom: 20px;
  277 +}
  278 +
  279 +.pagination-section {
  280 + text-align: right;
  281 + margin-top: 20px;
  282 +}
  283 +
  284 +.dialog-footer {
  285 + text-align: right;
  286 +}
  287 +</style>
  288 +
... ...
antis-ncc-admin/src/views/lqInventory/index.vue 0 → 100644
  1 +<template>
  2 + <div class="NCC-common-layout">
  3 + <div class="NCC-common-layout-center">
  4 + <!-- 搜索区域 -->
  5 + <el-row class="NCC-common-search-box" :gutter="16">
  6 + <el-form @submit.native.prevent>
  7 + <el-col :span="6">
  8 + <el-form-item label="产品名称">
  9 + <el-input v-model="query.productName" placeholder="请输入产品名称" clearable />
  10 + </el-form-item>
  11 + </el-col>
  12 + <el-col :span="6">
  13 + <el-form-item label="产品分类">
  14 + <el-input v-model="query.productCategory" placeholder="请输入产品分类" clearable />
  15 + </el-form-item>
  16 + </el-col>
  17 + <el-col :span="6">
  18 + <el-form-item label="负责部门">
  19 + <el-select v-model="query.departmentId" placeholder="请选择负责部门" clearable style="width: 100%">
  20 + <el-option v-for="dept in departmentList" :key="dept.id" :label="dept.name"
  21 + :value="dept.id">
  22 + </el-option>
  23 + </el-select>
  24 + </el-form-item>
  25 + </el-col>
  26 + <el-col :span="6">
  27 + <el-form-item>
  28 + <el-button type="primary" icon="el-icon-search" @click="search()">查询</el-button>
  29 + <el-button icon="el-icon-refresh-right" @click="reset()">重置</el-button>
  30 + </el-form-item>
  31 + </el-col>
  32 + </el-form>
  33 + </el-row>
  34 +
  35 + <!-- 主要内容区域 -->
  36 + <div class="NCC-common-layout-main NCC-flex-main">
  37 + <!-- 操作按钮区域 -->
  38 + <div class="NCC-common-head">
  39 + <div>
  40 + <el-button type="primary" icon="el-icon-plus" @click="addInventoryHandle()">添加库存</el-button>
  41 + <el-button type="success" icon="el-icon-edit" @click="editInventoryHandle()"
  42 + :disabled="selectedIds.length !== 1">编辑库存</el-button>
  43 + <el-button type="warning" icon="el-icon-s-operation"
  44 + @click="usageRecordHandle()">使用记录</el-button>
  45 + <el-button type="text" icon="el-icon-download" @click="exportData()">导出</el-button>
  46 + </div>
  47 + <div class="NCC-common-head-right">
  48 + <el-tooltip effect="dark" content="刷新" placement="top">
  49 + <el-link icon="icon-ym icon-ym-Refresh NCC-common-head-icon" :underline="false"
  50 + @click="reset()" />
  51 + </el-tooltip>
  52 + <screenfull isContainer />
  53 + </div>
  54 + </div>
  55 +
  56 + <!-- 库存列表表格 -->
  57 + <NCC-table v-loading="listLoading" :data="list" has-c @selection-change="handleSelectionChange">
  58 + <el-table-column prop="productName" label="产品名称" align="left" show-overflow-tooltip />
  59 + <el-table-column prop="productCategory" label="产品分类" align="left" width="120" />
  60 + <el-table-column prop="price" label="单价" align="right" width="100">
  61 + <template slot-scope="scope">
  62 + {{ formatMoney(scope.row.price) }}
  63 + </template>
  64 + </el-table-column>
  65 + <el-table-column prop="quantity" label="库存数量" align="right" width="100">
  66 + <template slot-scope="scope">
  67 + <span :class="scope.row.quantity <= 10 ? 'text-danger' : ''">{{ scope.row.quantity }}</span>
  68 + </template>
  69 + </el-table-column>
  70 + <el-table-column prop="standardUnit" label="单位" align="center" width="80" />
  71 + <el-table-column prop="totalValue" label="总价值" align="right" width="120">
  72 + <template slot-scope="scope">
  73 + {{ formatMoney(scope.row.totalValue) }}
  74 + </template>
  75 + </el-table-column>
  76 + <el-table-column prop="departmentName" label="负责部门" align="left" width="120" />
  77 + <el-table-column prop="createTime" label="创建时间" align="center" width="160">
  78 + <template slot-scope="scope">
  79 + {{ scope.row.createTime | dateTimeFormat }}
  80 + </template>
  81 + </el-table-column>
  82 + <el-table-column label="操作" align="center" width="200" fixed="right">
  83 + <template slot-scope="scope">
  84 + <el-button type="text" @click="viewInventoryInfo(scope.row)">查看详情</el-button>
  85 + <el-button type="text" @click="editInventory(scope.row)">编辑</el-button>
  86 + <el-button type="text" @click="viewUsageRecords(scope.row)">使用记录</el-button>
  87 + </template>
  88 + </el-table-column>
  89 + </NCC-table>
  90 +
  91 + <!-- 分页组件 -->
  92 + <pagination v-show="total > 0" :total="total" :page.sync="query.currentPage"
  93 + :limit.sync="query.pageSize" @pagination="getList" />
  94 + </div>
  95 + </div>
  96 +
  97 + <!-- 添加/编辑库存弹窗 -->
  98 + <InventoryForm v-if="inventoryFormVisible" ref="InventoryForm" @refreshDataList="getList" />
  99 +
  100 + <!-- 库存详情弹窗 -->
  101 + <InventoryInfoDialog v-if="inventoryInfoVisible" ref="InventoryInfoDialog" />
  102 +
  103 + <!-- 使用记录弹窗 -->
  104 + <UsageRecordDialog v-if="usageRecordVisible" ref="UsageRecordDialog" />
  105 + </div>
  106 +</template>
  107 +
  108 +<script>
  109 +import { getInventoryList } from '@/api/extend/lqInventory'
  110 +import { getUserList } from '@/api/permission/user'
  111 +import InventoryForm from './InventoryForm'
  112 +import InventoryInfoDialog from './InventoryInfoDialog'
  113 +import UsageRecordDialog from './UsageRecordDialog'
  114 +import Pagination from '@/components/Pagination'
  115 +
  116 +export default {
  117 + name: 'LqInventory',
  118 + components: {
  119 + InventoryForm,
  120 + InventoryInfoDialog,
  121 + UsageRecordDialog,
  122 + Pagination
  123 + },
  124 + data() {
  125 + return {
  126 + query: {
  127 + productName: '',
  128 + productCategory: '',
  129 + departmentId: '',
  130 + currentPage: 1,
  131 + pageSize: 20
  132 + },
  133 + list: [],
  134 + total: 0,
  135 + listLoading: true,
  136 + inventoryFormVisible: false,
  137 + inventoryInfoVisible: false,
  138 + usageRecordVisible: false,
  139 + selectedIds: [],
  140 + departmentList: [] // 部门列表
  141 + }
  142 + },
  143 + created() {
  144 + this.getDepartmentList()
  145 + this.getList()
  146 + },
  147 + methods: {
  148 + // 获取部门列表
  149 + getDepartmentList() {
  150 + const params = {
  151 + currentPage: 1,
  152 + pageSize: 1000, // 获取所有部门
  153 + enabledMark: 1 // 只获取启用的部门
  154 + }
  155 +
  156 + getUserList(params).then(response => {
  157 + if (response.code === 200) {
  158 + // 将用户列表转换为部门列表格式
  159 + this.departmentList = response.data.list.map(user => ({
  160 + id: user.id,
  161 + name: user.realName
  162 + }))
  163 + } else {
  164 + this.$message.error(response.msg || '获取部门列表失败')
  165 + }
  166 + }).catch(() => {
  167 + this.$message.error('获取部门列表失败')
  168 + })
  169 + },
  170 +
  171 + // 获取库存列表
  172 + getList() {
  173 + this.listLoading = true
  174 + getInventoryList(this.query).then(response => {
  175 + if (response.code === 200) {
  176 + this.list = response.data.list || []
  177 + this.total = (response.data.pagination && response.data.pagination.total) || 0
  178 + } else {
  179 + this.$message.error(response.msg || '获取库存列表失败')
  180 + }
  181 + this.listLoading = false
  182 + }).catch(() => {
  183 + this.listLoading = false
  184 + })
  185 + },
  186 +
  187 + // 搜索
  188 + search() {
  189 + this.query.currentPage = 1
  190 + this.getList()
  191 + },
  192 +
  193 + // 重置
  194 + reset() {
  195 + this.query = {
  196 + productName: '',
  197 + productCategory: '',
  198 + departmentId: '',
  199 + currentPage: 1,
  200 + pageSize: 20
  201 + }
  202 + this.getList()
  203 + },
  204 +
  205 + // 添加库存
  206 + addInventoryHandle() {
  207 + this.inventoryFormVisible = true
  208 + this.$nextTick(() => {
  209 + this.$refs.InventoryForm.init()
  210 + })
  211 + },
  212 +
  213 + // 编辑库存
  214 + editInventoryHandle() {
  215 + if (this.selectedIds.length === 0) {
  216 + this.$message.warning('请选择一个库存记录')
  217 + return
  218 + }
  219 + if (this.selectedIds.length > 1) {
  220 + this.$message.warning('请只选择一个库存记录')
  221 + return
  222 + }
  223 +
  224 + const selectedInventory = this.list.find(item => item.id === this.selectedIds[0])
  225 + if (selectedInventory) {
  226 + this.inventoryFormVisible = true
  227 + this.$nextTick(() => {
  228 + this.$refs.InventoryForm.init(selectedInventory.id)
  229 + })
  230 + }
  231 + },
  232 +
  233 + // 编辑库存(从操作列)
  234 + editInventory(row) {
  235 + this.inventoryFormVisible = true
  236 + this.$nextTick(() => {
  237 + this.$refs.InventoryForm.init(row.id)
  238 + })
  239 + },
  240 +
  241 + // 查看库存详情
  242 + viewInventoryInfo(row) {
  243 + this.inventoryInfoVisible = true
  244 + this.$nextTick(() => {
  245 + this.$refs.InventoryInfoDialog.init(row.id)
  246 + })
  247 + },
  248 +
  249 + // 使用记录管理
  250 + usageRecordHandle() {
  251 + this.usageRecordVisible = true
  252 + this.$nextTick(() => {
  253 + this.$refs.UsageRecordDialog.init()
  254 + })
  255 + },
  256 +
  257 + // 查看使用记录
  258 + viewUsageRecords(row) {
  259 + this.usageRecordVisible = true
  260 + this.$nextTick(() => {
  261 + this.$refs.UsageRecordDialog.init(row.id, row.productName)
  262 + })
  263 + },
  264 +
  265 + // 多选
  266 + handleSelectionChange(selection) {
  267 + this.selectedIds = selection.map(item => item.id)
  268 + },
  269 +
  270 + // 格式化金额
  271 + formatMoney(value) {
  272 + if (value === null || value === undefined || value === '') {
  273 + return '0.00'
  274 + }
  275 + return Number(value).toFixed(2)
  276 + },
  277 +
  278 + // 导出
  279 + exportData() {
  280 + this.$message.info('导出功能开发中...')
  281 + }
  282 + }
  283 +}
  284 +</script>
  285 +
  286 +<style scoped>
  287 +.NCC-common-layout {
  288 + height: 100%;
  289 +}
  290 +
  291 +.text-danger {
  292 + color: #f56c6c;
  293 + font-weight: bold;
  294 +}
  295 +</style>
... ...
antis-ncc-admin/src/views/lqStudyClass/AddStudentForm.vue 0 → 100644
  1 +<template>
  2 + <el-dialog title="添加学员" :visible.sync="visible" width="800px" @close="closeDialog">
  3 + <el-form ref="form" :model="form" :rules="rules" label-width="100px">
  4 + <el-row :gutter="20">
  5 + <el-col :span="12">
  6 + <el-form-item label="班级名称">
  7 + <el-input v-model="className" placeholder="班级名称" readonly />
  8 + </el-form-item>
  9 + </el-col>
  10 + <el-col :span="12">
  11 + <el-form-item label="班级ID">
  12 + <el-input v-model="form.classId" placeholder="班级ID" readonly />
  13 + </el-form-item>
  14 + </el-col>
  15 + </el-row>
  16 +
  17 + <!-- 学员信息 -->
  18 + <el-form-item label="学员信息">
  19 + <div class="student-section">
  20 + <div class="student-header">
  21 + <span>学员列表</span>
  22 + <el-button type="primary" size="small" icon="el-icon-plus" @click="addStudent">添加学员</el-button>
  23 + </div>
  24 + <el-table :data="form.students" border style="width: 100%; margin-top: 10px;">
  25 + <el-table-column prop="employeeId" label="选择学员" width="200">
  26 + <template slot-scope="scope">
  27 + <userSelect v-model="scope.row.employeeId" placeholder="请选择学员"
  28 + @change="(ids, users) => onStudentChange(scope.$index, ids, users)" size="small" />
  29 + </template>
  30 + </el-table-column>
  31 + <el-table-column prop="employeeName" label="学员姓名" width="120">
  32 + <template slot-scope="scope">
  33 + <el-input v-model="scope.row.employeeName" placeholder="学员姓名" size="small" readonly />
  34 + </template>
  35 + </el-table-column>
  36 + <el-table-column prop="employeePhone" label="手机号" width="140">
  37 + <template slot-scope="scope">
  38 + <el-input v-model="scope.row.employeePhone" placeholder="请输入手机号" size="small" />
  39 + </template>
  40 + </el-table-column>
  41 + <el-table-column prop="admissionTime" label="入学时间" width="140">
  42 + <template slot-scope="scope">
  43 + <el-date-picker v-model="scope.row.admissionTime" type="date" placeholder="选择时间"
  44 + value-format="yyyy-MM-dd" size="small" style="width: 100%">
  45 + </el-date-picker>
  46 + </template>
  47 + </el-table-column>
  48 + <el-table-column prop="hrBelong" label="HR归属" width="120">
  49 + <template slot-scope="scope">
  50 + <el-input v-model="scope.row.hrBelong" placeholder="请输入HR归属" size="small" />
  51 + </template>
  52 + </el-table-column>
  53 + <el-table-column label="操作" width="80">
  54 + <template slot-scope="scope">
  55 + <el-button type="text" size="small" @click="removeStudent(scope.$index)">删除</el-button>
  56 + </template>
  57 + </el-table-column>
  58 + </el-table>
  59 + </div>
  60 + </el-form-item>
  61 + </el-form>
  62 +
  63 + <div slot="footer" class="dialog-footer">
  64 + <el-button @click="closeDialog">取消</el-button>
  65 + <el-button type="primary" @click="submitForm" :loading="submitLoading">确定</el-button>
  66 + </div>
  67 + </el-dialog>
  68 +</template>
  69 +
  70 +<script>
  71 +import { addStudentsToClass } from '@/api/extend/lqStudyClass'
  72 +
  73 +export default {
  74 + name: 'AddStudentForm',
  75 + data() {
  76 + return {
  77 + visible: false,
  78 + submitLoading: false,
  79 + className: '',
  80 + form: {
  81 + classId: '',
  82 + students: []
  83 + },
  84 + rules: {
  85 + classId: [
  86 + { required: true, message: '班级ID不能为空', trigger: 'blur' }
  87 + ]
  88 + }
  89 + }
  90 + },
  91 + methods: {
  92 + init(classId = '', className = '') {
  93 + this.visible = true
  94 + this.className = className
  95 + this.form.classId = classId
  96 + this.form.students = []
  97 + },
  98 +
  99 + // 学员选择变化
  100 + onStudentChange(index, ids, users) {
  101 + if (users && users.length > 0) {
  102 + const user = users[0]
  103 + this.form.students[index].employeeName = user.fullName
  104 + // 手机号需要用户手动填写,因为用户选择组件没有提供手机号信息
  105 + } else {
  106 + this.form.students[index].employeeName = ''
  107 + }
  108 + },
  109 +
  110 + // 删除学员
  111 + removeStudent(index) {
  112 + this.form.students.splice(index, 1)
  113 + },
  114 +
  115 + // 提交表单
  116 + submitForm() {
  117 + this.$refs.form.validate((valid) => {
  118 + if (valid) {
  119 + if (this.form.students.length === 0) {
  120 + this.$message.warning('请至少添加一名学员')
  121 + return
  122 + }
  123 +
  124 + this.submitLoading = true
  125 + addStudentsToClass(this.form).then(response => {
  126 + if (response.code === 200) {
  127 + this.$message.success(response.message || '添加成功')
  128 + this.closeDialog()
  129 + this.$emit('refreshDataList')
  130 + } else {
  131 + this.$message.error(response.msg || '添加失败')
  132 + }
  133 + this.submitLoading = false
  134 + }).catch(() => {
  135 + this.submitLoading = false
  136 + })
  137 + }
  138 + })
  139 + },
  140 +
  141 + // 关闭弹窗
  142 + closeDialog() {
  143 + this.visible = false
  144 + this.className = ''
  145 + this.form = {
  146 + classId: '',
  147 + students: []
  148 + }
  149 + }
  150 + }
  151 +}
  152 +</script>
  153 +
  154 +<style scoped>
  155 +.student-section {
  156 + width: 100%;
  157 +}
  158 +
  159 +.student-header {
  160 + display: flex;
  161 + justify-content: space-between;
  162 + align-items: center;
  163 + font-weight: 600;
  164 + color: #303133;
  165 +}
  166 +</style>
... ...
antis-ncc-admin/src/views/lqStudyClass/CreateClassForm.vue 0 → 100644
  1 +<template>
  2 + <el-dialog title="创建学习班级" :visible.sync="visible" width="800px" @close="closeDialog">
  3 + <el-form ref="form" :model="form" :rules="rules" label-width="100px">
  4 + <el-row :gutter="20">
  5 + <el-col :span="12">
  6 + <el-form-item label="班级名称" prop="className">
  7 + <el-input v-model="form.className" placeholder="请输入班级名称" />
  8 + </el-form-item>
  9 + </el-col>
  10 + <el-col :span="12">
  11 + <el-form-item label="授课老师" prop="teacherId">
  12 + <userSelect v-model="form.teacherId" placeholder="请选择授课老师" @change="onTeacherChange" />
  13 + </el-form-item>
  14 + </el-col>
  15 + </el-row>
  16 +
  17 + <el-row :gutter="20">
  18 + <el-col :span="12">
  19 + <el-form-item label="开始时间" prop="startTime">
  20 + <el-date-picker v-model="form.startTime" type="datetime" placeholder="选择开始时间"
  21 + value-format="yyyy-MM-dd HH:mm:ss" style="width: 100%">
  22 + </el-date-picker>
  23 + </el-form-item>
  24 + </el-col>
  25 + <el-col :span="12">
  26 + <el-form-item label="结束时间" prop="endTime">
  27 + <el-date-picker v-model="form.endTime" type="datetime" placeholder="选择结束时间"
  28 + value-format="yyyy-MM-dd HH:mm:ss" style="width: 100%">
  29 + </el-date-picker>
  30 + </el-form-item>
  31 + </el-col>
  32 + </el-row>
  33 +
  34 + <el-form-item label="备注">
  35 + <el-input v-model="form.remark" type="textarea" :rows="3" placeholder="请输入备注信息" />
  36 + </el-form-item>
  37 +
  38 + <!-- 学员信息 -->
  39 + <el-form-item label="学员信息">
  40 + <div class="student-section">
  41 + <div class="student-header">
  42 + <span>学员列表</span>
  43 + <el-button type="primary" size="small" icon="el-icon-plus" @click="addStudent">添加学员</el-button>
  44 + </div>
  45 + <el-table :data="form.students" border style="width: 100%; margin-top: 10px;">
  46 + <el-table-column prop="employeeId" label="选择学员" width="200">
  47 + <template slot-scope="scope">
  48 + <userSelect v-model="scope.row.employeeId" placeholder="请选择学员"
  49 + @change="(ids, users) => onStudentChange(scope.$index, ids, users)" size="small" />
  50 + </template>
  51 + </el-table-column>
  52 + <el-table-column prop="employeeName" label="学员姓名" width="120">
  53 + <template slot-scope="scope">
  54 + <el-input v-model="scope.row.employeeName" placeholder="学员姓名" size="small" readonly />
  55 + </template>
  56 + </el-table-column>
  57 + <el-table-column prop="employeePhone" label="手机号" width="140">
  58 + <template slot-scope="scope">
  59 + <el-input v-model="scope.row.employeePhone" placeholder="请输入手机号" size="small" />
  60 + </template>
  61 + </el-table-column>
  62 + <el-table-column prop="admissionTime" label="入学时间" width="140">
  63 + <template slot-scope="scope">
  64 + <el-date-picker v-model="scope.row.admissionTime" type="date" placeholder="选择时间"
  65 + value-format="yyyy-MM-dd" size="small" style="width: 100%">
  66 + </el-date-picker>
  67 + </template>
  68 + </el-table-column>
  69 + <el-table-column prop="hrBelong" label="HR归属" width="120">
  70 + <template slot-scope="scope">
  71 + <el-input v-model="scope.row.hrBelong" placeholder="请输入HR归属" size="small" />
  72 + </template>
  73 + </el-table-column>
  74 + <el-table-column label="操作" width="80">
  75 + <template slot-scope="scope">
  76 + <el-button type="text" size="small" @click="removeStudent(scope.$index)">删除</el-button>
  77 + </template>
  78 + </el-table-column>
  79 + </el-table>
  80 + </div>
  81 + </el-form-item>
  82 + </el-form>
  83 +
  84 + <div slot="footer" class="dialog-footer">
  85 + <el-button @click="closeDialog">取消</el-button>
  86 + <el-button type="primary" @click="submitForm" :loading="submitLoading">确定</el-button>
  87 + </div>
  88 + </el-dialog>
  89 +</template>
  90 +
  91 +<script>
  92 +import { createClassWithStudents } from '@/api/extend/lqStudyClass'
  93 +
  94 +export default {
  95 + name: 'CreateClassForm',
  96 + data() {
  97 + return {
  98 + visible: false,
  99 + submitLoading: false,
  100 + form: {
  101 + className: '',
  102 + teacherId: '',
  103 + teacherName: '',
  104 + startTime: '',
  105 + endTime: '',
  106 + remark: '',
  107 + students: []
  108 + },
  109 + rules: {
  110 + className: [
  111 + { required: true, message: '请输入班级名称', trigger: 'blur' }
  112 + ],
  113 + teacherId: [
  114 + { required: true, message: '请选择授课老师', trigger: 'change' }
  115 + ],
  116 + startTime: [
  117 + { required: true, message: '请选择开始时间', trigger: 'change' }
  118 + ],
  119 + endTime: [
  120 + { required: true, message: '请选择结束时间', trigger: 'change' }
  121 + ]
  122 + }
  123 + }
  124 + },
  125 + methods: {
  126 + init() {
  127 + this.visible = true
  128 + this.resetForm()
  129 + },
  130 +
  131 + resetForm() {
  132 + this.form = {
  133 + className: '',
  134 + teacherId: '',
  135 + teacherName: '',
  136 + startTime: '',
  137 + endTime: '',
  138 + remark: '',
  139 + students: []
  140 + }
  141 + this.$nextTick(() => {
  142 + if (this.$refs.form) {
  143 + this.$refs.form.clearValidate()
  144 + }
  145 + })
  146 + },
  147 +
  148 + // 老师选择变化
  149 + onTeacherChange(ids, users) {
  150 + if (users && users.length > 0) {
  151 + this.form.teacherName = users[0].fullName
  152 + } else {
  153 + this.form.teacherName = ''
  154 + }
  155 + },
  156 +
  157 + // 学员选择变化
  158 + onStudentChange(index, ids, users) {
  159 + if (users && users.length > 0) {
  160 + const user = users[0]
  161 + this.form.students[index].employeeName = user.fullName
  162 + // 手机号需要用户手动填写,因为用户选择组件没有提供手机号信息
  163 + } else {
  164 + this.form.students[index].employeeName = ''
  165 + }
  166 + },
  167 +
  168 + // 添加学员
  169 + addStudent() {
  170 + this.form.students.push({
  171 + employeeName: '',
  172 + employeePhone: '',
  173 + employeeId: '',
  174 + admissionTime: '',
  175 + hrBelong: ''
  176 + })
  177 + },
  178 +
  179 + // 提交表单
  180 + submitForm() {
  181 + this.$refs.form.validate((valid) => {
  182 + if (valid) {
  183 + if (this.form.students.length === 0) {
  184 + this.$message.warning('请至少添加一名学员')
  185 + return
  186 + }
  187 +
  188 + this.submitLoading = true
  189 + createClassWithStudents(this.form).then(response => {
  190 + if (response.code === 200) {
  191 + this.$message.success(response.message || '创建成功')
  192 + this.closeDialog()
  193 + this.$emit('refreshDataList')
  194 + } else {
  195 + this.$message.error(response.msg || '创建失败')
  196 + }
  197 + this.submitLoading = false
  198 + }).catch(() => {
  199 + this.submitLoading = false
  200 + })
  201 + }
  202 + })
  203 + },
  204 +
  205 + // 关闭弹窗
  206 + closeDialog() {
  207 + this.visible = false
  208 + this.resetForm()
  209 + }
  210 + }
  211 +}
  212 +</script>
  213 +
  214 +<style scoped>
  215 +.student-section {
  216 + width: 100%;
  217 +}
  218 +
  219 +.student-header {
  220 + display: flex;
  221 + justify-content: space-between;
  222 + align-items: center;
  223 + font-weight: 600;
  224 + color: #303133;
  225 +}
  226 +</style>
... ...
antis-ncc-admin/src/views/lqStudyClass/StudentListDialog.vue 0 → 100644
  1 +<template>
  2 + <el-dialog title="班级学员列表" :visible.sync="visible" width="1000px" @close="closeDialog">
  3 + <div class="student-list-container">
  4 + <!-- 搜索区域 -->
  5 + <div class="search-section">
  6 + <el-form :model="query" :inline="true" class="search-form">
  7 + <el-form-item label="学员姓名">
  8 + <el-input v-model="query.employeeName" placeholder="请输入学员姓名" clearable size="small" />
  9 + </el-form-item>
  10 + <el-form-item label="手机号">
  11 + <el-input v-model="query.employeePhone" placeholder="请输入手机号" clearable size="small" />
  12 + </el-form-item>
  13 + <el-form-item label="员工ID">
  14 + <el-input v-model="query.employeeId" placeholder="请输入员工ID" clearable size="small" />
  15 + </el-form-item>
  16 + <el-form-item label="HR归属">
  17 + <el-input v-model="query.hrBelong" placeholder="请输入HR归属" clearable size="small" />
  18 + </el-form-item>
  19 + <el-form-item>
  20 + <el-button type="primary" size="small" @click="search">搜索</el-button>
  21 + <el-button size="small" @click="reset">重置</el-button>
  22 + </el-form-item>
  23 + </el-form>
  24 + </div>
  25 +
  26 + <!-- 学员列表 -->
  27 + <div class="table-section">
  28 + <el-table :data="studentList" v-loading="loading" border stripe style="width: 100%">
  29 + <el-table-column prop="employeeName" label="学员姓名" width="120" fixed="left" />
  30 + <el-table-column prop="employeePhone" label="手机号" width="140" />
  31 + <el-table-column prop="employeeId" label="员工ID" width="120" />
  32 + <el-table-column prop="admissionTime" label="入学时间" width="120">
  33 + <template slot-scope="scope">
  34 + {{ scope.row.admissionTime | dateFormat }}
  35 + </template>
  36 + </el-table-column>
  37 + <el-table-column prop="className" label="班级名称" width="150" />
  38 + <el-table-column prop="hrBelong" label="HR归属" width="120" />
  39 + <el-table-column label="操作" width="120" fixed="right">
  40 + <template slot-scope="scope">
  41 + <el-button type="text" size="small" @click="viewStudyRecords(scope.row)">学习记录</el-button>
  42 + </template>
  43 + </el-table-column>
  44 + </el-table>
  45 +
  46 + <!-- 分页 -->
  47 + <div class="pagination-section">
  48 + <el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange"
  49 + :current-page="pagination.pageIndex" :page-sizes="[10, 20, 50, 100]"
  50 + :page-size="pagination.pageSize" layout="total, sizes, prev, pager, next, jumper"
  51 + :total="pagination.total">
  52 + </el-pagination>
  53 + </div>
  54 + </div>
  55 + </div>
  56 +
  57 + <div slot="footer" class="dialog-footer">
  58 + <el-button @click="closeDialog">关闭</el-button>
  59 + </div>
  60 + </el-dialog>
  61 +</template>
  62 +
  63 +<script>
  64 +import { getStudentListByClassId } from '@/api/extend/lqStudyClass'
  65 +
  66 +export default {
  67 + name: 'StudentListDialog',
  68 + data() {
  69 + return {
  70 + visible: false,
  71 + loading: false,
  72 + classId: '',
  73 + className: '',
  74 + studentList: [],
  75 + query: {
  76 + employeeName: '',
  77 + employeePhone: '',
  78 + employeeId: '',
  79 + hrBelong: '',
  80 + classId: ''
  81 + },
  82 + pagination: {
  83 + pageIndex: 1,
  84 + pageSize: 20,
  85 + total: 0
  86 + }
  87 + }
  88 + },
  89 + methods: {
  90 + init(classId, className) {
  91 + this.visible = true
  92 + this.classId = classId
  93 + this.className = className
  94 + this.query.classId = classId
  95 + this.getStudentList()
  96 + },
  97 +
  98 + // 获取学员列表
  99 + getStudentList() {
  100 + this.loading = true
  101 + const params = {
  102 + ...this.query,
  103 + currentPage: this.pagination.pageIndex,
  104 + pageSize: this.pagination.pageSize
  105 + }
  106 +
  107 + getStudentListByClassId(params).then(response => {
  108 + if (response.code === 200) {
  109 + this.studentList = response.data.list || []
  110 + this.pagination.total = (response.data.pagination && response.data.pagination.total) || 0
  111 + } else {
  112 + this.$message.error(response.msg || '获取学员列表失败')
  113 + }
  114 + this.loading = false
  115 + }).catch(() => {
  116 + this.loading = false
  117 + })
  118 + },
  119 +
  120 + // 搜索
  121 + search() {
  122 + this.pagination.pageIndex = 1
  123 + this.getStudentList()
  124 + },
  125 +
  126 + // 重置
  127 + reset() {
  128 + this.query = {
  129 + employeeName: '',
  130 + employeePhone: '',
  131 + employeeId: '',
  132 + hrBelong: '',
  133 + classId: this.classId
  134 + }
  135 + this.pagination.pageIndex = 1
  136 + this.getStudentList()
  137 + },
  138 +
  139 + // 分页大小改变
  140 + handleSizeChange(val) {
  141 + this.pagination.pageSize = val
  142 + this.pagination.pageIndex = 1
  143 + this.getStudentList()
  144 + },
  145 +
  146 + // 当前页改变
  147 + handleCurrentChange(val) {
  148 + this.pagination.pageIndex = val
  149 + this.getStudentList()
  150 + },
  151 +
  152 + // 查看学习记录
  153 + viewStudyRecords(row) {
  154 + this.$emit('viewStudyRecords', row)
  155 + },
  156 +
  157 + // 关闭弹窗
  158 + closeDialog() {
  159 + this.visible = false
  160 + this.studentList = []
  161 + this.query = {
  162 + employeeName: '',
  163 + employeePhone: '',
  164 + employeeId: '',
  165 + hrBelong: '',
  166 + classId: ''
  167 + }
  168 + this.pagination = {
  169 + pageIndex: 1,
  170 + pageSize: 20,
  171 + total: 0
  172 + }
  173 + }
  174 + }
  175 +}
  176 +</script>
  177 +
  178 +<style scoped>
  179 +.student-list-container {
  180 + padding: 20px;
  181 +}
  182 +
  183 +.search-section {
  184 + margin-bottom: 20px;
  185 + padding: 15px;
  186 + background: #f5f7fa;
  187 + border-radius: 4px;
  188 +}
  189 +
  190 +.search-form .el-form-item {
  191 + margin-bottom: 10px;
  192 +}
  193 +
  194 +.table-section {
  195 + margin-bottom: 20px;
  196 +}
  197 +
  198 +.pagination-section {
  199 + text-align: right;
  200 + margin-top: 20px;
  201 +}
  202 +</style>
... ...
antis-ncc-admin/src/views/lqStudyClass/StudyRecordDialog.vue 0 → 100644
  1 +<template>
  2 + <el-dialog title="学习记录管理" :visible.sync="visible" width="1200px" @close="closeDialog">
  3 + <div class="study-record-container">
  4 + <!-- 搜索区域 -->
  5 + <div class="search-section">
  6 + <el-form :model="query" :inline="true" class="search-form">
  7 + <el-form-item label="学员姓名">
  8 + <el-input v-model="query.employeeName" placeholder="请输入学员姓名" clearable size="small" />
  9 + </el-form-item>
  10 + <el-form-item label="员工ID">
  11 + <el-input v-model="query.employeeId" placeholder="请输入员工ID" clearable size="small" />
  12 + </el-form-item>
  13 + <el-form-item label="学习类型">
  14 + <el-input v-model="query.studyType" placeholder="请输入学习类型" clearable size="small" />
  15 + </el-form-item>
  16 + <el-form-item label="学习日期">
  17 + <el-date-picker v-model="query.studyDateRange" type="daterange" range-separator="至"
  18 + start-placeholder="开始日期" end-placeholder="结束日期" value-format="yyyy-MM-dd" size="small">
  19 + </el-date-picker>
  20 + </el-form-item>
  21 + <el-form-item label="日常状态">
  22 + <el-input v-model="query.dailyStatus" placeholder="请输入日常状态" clearable size="small" />
  23 + </el-form-item>
  24 + <el-form-item>
  25 + <el-button type="primary" size="small" @click="search">搜索</el-button>
  26 + <el-button size="small" @click="reset">重置</el-button>
  27 + <el-button type="success" size="small" icon="el-icon-plus" @click="addRecord">添加记录</el-button>
  28 + </el-form-item>
  29 + </el-form>
  30 + </div>
  31 +
  32 + <!-- 学习记录列表 -->
  33 + <div class="table-section">
  34 + <el-table :data="recordList" v-loading="loading" border stripe style="width: 100%">
  35 + <el-table-column prop="employeeName" label="学员姓名" width="100" fixed="left" />
  36 + <el-table-column prop="employeeId" label="员工ID" width="120" />
  37 + <el-table-column prop="studyType" label="学习类型" width="120" />
  38 + <el-table-column prop="transportFee" label="交通费" width="100" align="center">
  39 + <template slot-scope="scope">
  40 + {{ formatMoney(scope.row.transportFee) }}
  41 + </template>
  42 + </el-table-column>
  43 + <el-table-column prop="studyDate" label="学习日期" width="120">
  44 + <template slot-scope="scope">
  45 + {{ scope.row.studyDate | dateFormat }}
  46 + </template>
  47 + </el-table-column>
  48 + <el-table-column prop="dailyStatus" label="日常状态" width="120" />
  49 + <el-table-column prop="remark" label="备注" show-overflow-tooltip />
  50 + <el-table-column prop="isStoreAssist" label="下店协助" width="100" align="center">
  51 + <template slot-scope="scope">
  52 + <el-tag :type="scope.row.isStoreAssist === 1 ? 'success' : 'info'" size="mini">
  53 + {{ scope.row.isStoreAssist === 1 ? '是' : '否' }}
  54 + </el-tag>
  55 + </template>
  56 + </el-table-column>
  57 + <el-table-column prop="storeName" label="协助门店" width="120" />
  58 + <el-table-column prop="createUserName" label="创建人" width="100" />
  59 + <el-table-column prop="createTime" label="创建时间" width="160">
  60 + <template slot-scope="scope">
  61 + {{ scope.row.createTime | dateTimeFormat }}
  62 + </template>
  63 + </el-table-column>
  64 + <el-table-column label="操作" width="120" fixed="right">
  65 + <template slot-scope="scope">
  66 + <el-button type="text" size="small" @click="cancelRecord(scope.row)">作废</el-button>
  67 + </template>
  68 + </el-table-column>
  69 + </el-table>
  70 +
  71 + <!-- 分页 -->
  72 + <div class="pagination-section">
  73 + <el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange"
  74 + :current-page="pagination.pageIndex" :page-sizes="[10, 20, 50, 100]"
  75 + :page-size="pagination.pageSize" layout="total, sizes, prev, pager, next, jumper"
  76 + :total="pagination.total">
  77 + </el-pagination>
  78 + </div>
  79 + </div>
  80 + </div>
  81 +
  82 + <div slot="footer" class="dialog-footer">
  83 + <el-button @click="closeDialog">关闭</el-button>
  84 + </div>
  85 +
  86 + <!-- 添加学习记录弹窗 -->
  87 + <el-dialog title="添加学习记录" :visible.sync="addRecordVisible" width="600px" append-to-body>
  88 + <el-form ref="recordForm" :model="recordForm" :rules="recordRules" label-width="100px">
  89 + <el-form-item label="学员姓名" prop="employeeName">
  90 + <el-input v-model="recordForm.employeeName" placeholder="请输入学员姓名" />
  91 + </el-form-item>
  92 + <el-form-item label="员工ID" prop="employeeId">
  93 + <el-input v-model="recordForm.employeeId" placeholder="请输入员工ID" />
  94 + </el-form-item>
  95 + <el-form-item label="学习类型" prop="studyType">
  96 + <el-input v-model="recordForm.studyType" placeholder="请输入学习类型" />
  97 + </el-form-item>
  98 + <el-form-item label="交通费">
  99 + <el-input-number v-model="recordForm.transportFee" :min="0" :precision="2" style="width: 100%" />
  100 + </el-form-item>
  101 + <el-form-item label="学习日期" prop="studyDate">
  102 + <el-date-picker v-model="recordForm.studyDate" type="date" placeholder="选择学习日期"
  103 + value-format="yyyy-MM-dd" style="width: 100%">
  104 + </el-date-picker>
  105 + </el-form-item>
  106 + <el-form-item label="日常状态" prop="dailyStatus">
  107 + <el-input v-model="recordForm.dailyStatus" placeholder="请输入日常状态" />
  108 + </el-form-item>
  109 + <el-form-item label="是否下店协助">
  110 + <el-switch v-model="recordForm.isStoreAssist" :active-value="1" :inactive-value="0" />
  111 + </el-form-item>
  112 + <el-form-item v-if="recordForm.isStoreAssist === 1" label="门店ID" prop="storeId">
  113 + <el-input v-model="recordForm.storeId" placeholder="请输入门店ID" />
  114 + </el-form-item>
  115 + <el-form-item v-if="recordForm.isStoreAssist === 1" label="门店名称" prop="storeName">
  116 + <el-input v-model="recordForm.storeName" placeholder="请输入门店名称" />
  117 + </el-form-item>
  118 + <el-form-item label="备注">
  119 + <el-input v-model="recordForm.remark" type="textarea" :rows="3" placeholder="请输入备注信息" />
  120 + </el-form-item>
  121 + </el-form>
  122 + <div slot="footer" class="dialog-footer">
  123 + <el-button @click="addRecordVisible = false">取消</el-button>
  124 + <el-button type="primary" @click="submitRecord" :loading="submitLoading">确定</el-button>
  125 + </div>
  126 + </el-dialog>
  127 + </el-dialog>
  128 +</template>
  129 +
  130 +<script>
  131 +import { getStudyRecordList, addStudyRecord, cancelStudyRecord, getStudentListByClassId } from '@/api/extend/lqStudyClass'
  132 +
  133 +export default {
  134 + name: 'StudyRecordDialog',
  135 + data() {
  136 + return {
  137 + visible: false,
  138 + loading: false,
  139 + submitLoading: false,
  140 + addRecordVisible: false,
  141 + classId: '',
  142 + className: '',
  143 + studentIds: [], // 班级学员ID列表
  144 + recordList: [],
  145 + query: {
  146 + employeeName: '',
  147 + employeeId: '',
  148 + studyType: '',
  149 + studyDateStart: '',
  150 + studyDateEnd: '',
  151 + dailyStatus: '',
  152 + studyDateRange: []
  153 + },
  154 + pagination: {
  155 + pageIndex: 1,
  156 + pageSize: 20,
  157 + total: 0
  158 + },
  159 + recordForm: {
  160 + employeeName: '',
  161 + employeeId: '',
  162 + studyType: '',
  163 + transportFee: 0,
  164 + studyDate: '',
  165 + dailyStatus: '',
  166 + remark: '',
  167 + isStoreAssist: 0,
  168 + storeId: '',
  169 + storeName: ''
  170 + },
  171 + recordRules: {
  172 + employeeName: [
  173 + { required: true, message: '请输入学员姓名', trigger: 'blur' }
  174 + ],
  175 + employeeId: [
  176 + { required: true, message: '请输入员工ID', trigger: 'blur' }
  177 + ],
  178 + studyType: [
  179 + { required: true, message: '请输入学习类型', trigger: 'blur' }
  180 + ],
  181 + studyDate: [
  182 + { required: true, message: '请选择学习日期', trigger: 'change' }
  183 + ],
  184 + dailyStatus: [
  185 + { required: true, message: '请输入日常状态', trigger: 'blur' }
  186 + ]
  187 + }
  188 + }
  189 + },
  190 + methods: {
  191 + init(classId, className) {
  192 + this.visible = true
  193 + this.classId = classId
  194 + this.className = className
  195 + this.getStudentIds(classId)
  196 + },
  197 +
  198 + // 获取班级下的学员ID列表
  199 + getStudentIds(classId) {
  200 + const params = {
  201 + classId: classId,
  202 + currentPage: 1,
  203 + pageSize: 1000 // 获取所有学员
  204 + }
  205 +
  206 + getStudentListByClassId(params).then(response => {
  207 + if (response.code === 200) {
  208 + const students = response.data.list || []
  209 + this.studentIds = students.map(student => student.employeeId).filter(id => id)
  210 + this.getRecordList()
  211 + } else {
  212 + this.$message.error(response.msg || '获取学员列表失败')
  213 + this.loading = false
  214 + }
  215 + }).catch(() => {
  216 + this.loading = false
  217 + })
  218 + },
  219 + // 获取学习记录列表
  220 + getRecordList() {
  221 + this.loading = true
  222 + const params = {
  223 + ...this.query,
  224 + currentPage: this.pagination.pageIndex,
  225 + pageSize: this.pagination.pageSize
  226 + }
  227 +
  228 + // 处理日期范围
  229 + if (this.query.studyDateRange && this.query.studyDateRange.length === 2) {
  230 + params.studyDateStart = this.query.studyDateRange[0]
  231 + params.studyDateEnd = this.query.studyDateRange[1]
  232 + }
  233 +
  234 + getStudyRecordList(params).then(response => {
  235 + if (response.code === 200) {
  236 + let recordList = response.data.list || []
  237 + // 按班级学员ID过滤学习记录
  238 + if (this.studentIds && this.studentIds.length > 0) {
  239 + recordList = recordList.filter(record => this.studentIds.includes(record.employeeId))
  240 + }
  241 + this.recordList = recordList
  242 + this.pagination.total = recordList.length
  243 + } else {
  244 + this.$message.error(response.msg || '获取学习记录失败')
  245 + }
  246 + this.loading = false
  247 + }).catch(() => {
  248 + this.loading = false
  249 + })
  250 + },
  251 +
  252 + // 搜索
  253 + search() {
  254 + this.pagination.pageIndex = 1
  255 + this.getRecordList()
  256 + },
  257 +
  258 + // 重置
  259 + reset() {
  260 + this.query = {
  261 + employeeName: '',
  262 + employeeId: '',
  263 + studyType: '',
  264 + studyDateStart: '',
  265 + studyDateEnd: '',
  266 + dailyStatus: '',
  267 + studyDateRange: []
  268 + }
  269 + this.pagination.pageIndex = 1
  270 + this.getRecordList()
  271 + },
  272 +
  273 + // 分页大小改变
  274 + handleSizeChange(val) {
  275 + this.pagination.pageSize = val
  276 + this.pagination.pageIndex = 1
  277 + this.getRecordList()
  278 + },
  279 +
  280 + // 当前页改变
  281 + handleCurrentChange(val) {
  282 + this.pagination.pageIndex = val
  283 + this.getRecordList()
  284 + },
  285 +
  286 + // 添加记录
  287 + addRecord() {
  288 + this.addRecordVisible = true
  289 + this.resetRecordForm()
  290 + },
  291 +
  292 + // 重置记录表单
  293 + resetRecordForm() {
  294 + this.recordForm = {
  295 + employeeName: '',
  296 + employeeId: '',
  297 + studyType: '',
  298 + transportFee: 0,
  299 + studyDate: '',
  300 + dailyStatus: '',
  301 + remark: '',
  302 + isStoreAssist: 0,
  303 + storeId: '',
  304 + storeName: ''
  305 + }
  306 + this.$nextTick(() => {
  307 + if (this.$refs.recordForm) {
  308 + this.$refs.recordForm.clearValidate()
  309 + }
  310 + })
  311 + },
  312 +
  313 + // 提交记录
  314 + submitRecord() {
  315 + this.$refs.recordForm.validate((valid) => {
  316 + if (valid) {
  317 + this.submitLoading = true
  318 + addStudyRecord(this.recordForm).then(response => {
  319 + if (response.code === 200) {
  320 + this.$message.success('添加成功')
  321 + this.addRecordVisible = false
  322 + this.getRecordList()
  323 + } else {
  324 + this.$message.error(response.msg || '添加失败')
  325 + }
  326 + this.submitLoading = false
  327 + }).catch(() => {
  328 + this.submitLoading = false
  329 + })
  330 + }
  331 + })
  332 + },
  333 +
  334 + // 作废记录
  335 + cancelRecord(row) {
  336 + this.$confirm('确定要作废该学习记录吗?', '提示', {
  337 + confirmButtonText: '确定',
  338 + cancelButtonText: '取消',
  339 + type: 'warning'
  340 + }).then(() => {
  341 + cancelStudyRecord(row.id).then(response => {
  342 + if (response.code === 200) {
  343 + this.$message.success('作废成功')
  344 + this.getRecordList()
  345 + } else {
  346 + this.$message.error(response.msg || '作废失败')
  347 + }
  348 + })
  349 + })
  350 + },
  351 +
  352 + // 格式化金额
  353 + formatMoney(value) {
  354 + if (value === null || value === undefined || value === '') {
  355 + return '0.00'
  356 + }
  357 + return Number(value).toFixed(2)
  358 + },
  359 +
  360 + // 关闭弹窗
  361 + closeDialog() {
  362 + this.visible = false
  363 + this.recordList = []
  364 + this.query = {
  365 + employeeName: '',
  366 + employeeId: '',
  367 + studyType: '',
  368 + studyDateStart: '',
  369 + studyDateEnd: '',
  370 + dailyStatus: '',
  371 + studyDateRange: []
  372 + }
  373 + this.pagination = {
  374 + pageIndex: 1,
  375 + pageSize: 20,
  376 + total: 0
  377 + }
  378 + }
  379 + }
  380 +}
  381 +</script>
  382 +
  383 +<style scoped>
  384 +.study-record-container {
  385 + padding: 20px;
  386 +}
  387 +
  388 +.search-section {
  389 + margin-bottom: 20px;
  390 + padding: 15px;
  391 + background: #f5f7fa;
  392 + border-radius: 4px;
  393 +}
  394 +
  395 +.search-form .el-form-item {
  396 + margin-bottom: 10px;
  397 +}
  398 +
  399 +.table-section {
  400 + margin-bottom: 20px;
  401 +}
  402 +
  403 +.pagination-section {
  404 + text-align: right;
  405 + margin-top: 20px;
  406 +}
  407 +</style>
... ...
antis-ncc-admin/src/views/lqStudyClass/index.vue 0 → 100644
  1 +<template>
  2 + <div class="NCC-common-layout">
  3 + <div class="NCC-common-layout-center">
  4 + <!-- 搜索区域 -->
  5 + <el-row class="NCC-common-search-box" :gutter="16">
  6 + <el-form @submit.native.prevent>
  7 + <el-col :span="6">
  8 + <el-form-item label="班级名称">
  9 + <el-input v-model="query.className" placeholder="请输入班级名称" clearable />
  10 + </el-form-item>
  11 + </el-col>
  12 + <el-col :span="6">
  13 + <el-form-item label="授课老师">
  14 + <userSelect v-model="query.teacherId" placeholder="请选择授课老师" clearable />
  15 + </el-form-item>
  16 + </el-col>
  17 + <el-col :span="6">
  18 + <el-form-item label="开始时间">
  19 + <el-date-picker v-model="query.startTime" type="date" placeholder="选择开始时间"
  20 + value-format="yyyy-MM-dd" clearable>
  21 + </el-date-picker>
  22 + </el-form-item>
  23 + </el-col>
  24 + <el-col :span="6">
  25 + <el-form-item>
  26 + <el-button type="primary" icon="el-icon-search" @click="search()">查询</el-button>
  27 + <el-button icon="el-icon-refresh-right" @click="reset()">重置</el-button>
  28 + </el-form-item>
  29 + </el-col>
  30 + </el-form>
  31 + </el-row>
  32 +
  33 + <!-- 主要内容区域 -->
  34 + <div class="NCC-common-layout-main NCC-flex-main">
  35 + <!-- 操作按钮区域 -->
  36 + <div class="NCC-common-head">
  37 + <div>
  38 + <el-button type="primary" icon="el-icon-plus" @click="addClassHandle()">创建班级</el-button>
  39 + <el-button type="success" icon="el-icon-user"
  40 + @click="addStudentHandle()">添加学员(需选择班级)</el-button>
  41 + <el-button type="text" icon="el-icon-download" @click="exportData()">导出</el-button>
  42 + </div>
  43 + <div class="NCC-common-head-right">
  44 + <el-tooltip effect="dark" content="刷新" placement="top">
  45 + <el-link icon="icon-ym icon-ym-Refresh NCC-common-head-icon" :underline="false"
  46 + @click="reset()" />
  47 + </el-tooltip>
  48 + <screenfull isContainer />
  49 + </div>
  50 + </div>
  51 +
  52 + <!-- 班级列表表格 -->
  53 + <NCC-table v-loading="listLoading" :data="list" has-c @selection-change="handleSelectionChange">
  54 + <el-table-column prop="className" label="班级名称" align="left" show-overflow-tooltip />
  55 + <el-table-column prop="teacherName" label="授课老师" align="left" show-overflow-tooltip />
  56 + <el-table-column prop="startTime" label="开始时间" align="center" width="120">
  57 + <template slot-scope="scope">
  58 + {{ scope.row.startTime | dateFormat }}
  59 + </template>
  60 + </el-table-column>
  61 + <el-table-column prop="endTime" label="结束时间" align="center" width="120">
  62 + <template slot-scope="scope">
  63 + {{ scope.row.endTime | dateFormat }}
  64 + </template>
  65 + </el-table-column>
  66 + <el-table-column prop="remark" label="备注" align="left" show-overflow-tooltip />
  67 + <el-table-column label="操作" align="center" width="200" fixed="right">
  68 + <template slot-scope="scope">
  69 + <el-button type="text" @click="viewStudents(scope.row)">查看学员</el-button>
  70 + <el-button type="text" @click="addStudentsToClass(scope.row)">添加学员</el-button>
  71 + <el-button type="text" @click="viewStudyRecords(scope.row)">学习记录</el-button>
  72 + </template>
  73 + </el-table-column>
  74 + </NCC-table>
  75 +
  76 + <!-- 分页组件 -->
  77 + <pagination v-show="total > 0" :total="total" :page.sync="query.currentPage"
  78 + :limit.sync="query.pageSize" @pagination="getList" />
  79 + </div>
  80 + </div>
  81 +
  82 + <!-- 创建班级弹窗 -->
  83 + <CreateClassForm v-if="createClassVisible" ref="CreateClassForm" @refreshDataList="getList" />
  84 +
  85 + <!-- 添加学员弹窗 -->
  86 + <AddStudentForm v-if="addStudentVisible" ref="AddStudentForm" @refreshDataList="getList" />
  87 +
  88 + <!-- 学员列表弹窗 -->
  89 + <StudentListDialog v-if="studentListVisible" ref="StudentListDialog"
  90 + @viewStudyRecords="handleViewStudyRecords" />
  91 +
  92 + <!-- 学习记录弹窗 -->
  93 + <StudyRecordDialog v-if="studyRecordVisible" ref="StudyRecordDialog" />
  94 + </div>
  95 +</template>
  96 +
  97 +<script>
  98 +import { getClassList } from '@/api/extend/lqStudyClass'
  99 +import CreateClassForm from './CreateClassForm'
  100 +import AddStudentForm from './AddStudentForm'
  101 +import StudentListDialog from './StudentListDialog'
  102 +import StudyRecordDialog from './StudyRecordDialog'
  103 +import Pagination from '@/components/Pagination'
  104 +
  105 +export default {
  106 + name: 'LqStudyClass',
  107 + components: {
  108 + CreateClassForm,
  109 + AddStudentForm,
  110 + StudentListDialog,
  111 + StudyRecordDialog,
  112 + Pagination
  113 + },
  114 + data() {
  115 + return {
  116 + query: {
  117 + className: '',
  118 + teacherId: '',
  119 + startTime: '',
  120 + endTime: '',
  121 + currentPage: 1,
  122 + pageSize: 20
  123 + },
  124 + list: [],
  125 + total: 0,
  126 + listLoading: true,
  127 + createClassVisible: false,
  128 + addStudentVisible: false,
  129 + studentListVisible: false,
  130 + studyRecordVisible: false,
  131 + selectedIds: []
  132 + }
  133 + },
  134 + created() {
  135 + this.getList()
  136 + },
  137 + methods: {
  138 + // 获取班级列表
  139 + getList() {
  140 + this.listLoading = true
  141 + getClassList(this.query).then(response => {
  142 + if (response.code === 200) {
  143 + this.list = response.data.list || []
  144 + this.total = (response.data.pagination && response.data.pagination.total) || 0
  145 + } else {
  146 + this.$message.error(response.msg || '获取班级列表失败')
  147 + }
  148 + this.listLoading = false
  149 + }).catch(() => {
  150 + this.listLoading = false
  151 + })
  152 + },
  153 +
  154 + // 搜索
  155 + search() {
  156 + this.query.currentPage = 1
  157 + this.getList()
  158 + },
  159 +
  160 + // 重置
  161 + reset() {
  162 + this.query = {
  163 + className: '',
  164 + teacherId: '',
  165 + startTime: '',
  166 + endTime: '',
  167 + currentPage: 1,
  168 + pageSize: 20
  169 + }
  170 + this.getList()
  171 + },
  172 +
  173 + // 创建班级
  174 + addClassHandle() {
  175 + this.createClassVisible = true
  176 + this.$nextTick(() => {
  177 + this.$refs.CreateClassForm.init()
  178 + })
  179 + },
  180 +
  181 + // 添加学员
  182 + addStudentHandle() {
  183 + if (this.selectedIds.length === 0) {
  184 + this.$message.warning('请先选择一个班级')
  185 + return
  186 + }
  187 + if (this.selectedIds.length > 1) {
  188 + this.$message.warning('请只选择一个班级')
  189 + return
  190 + }
  191 +
  192 + // 找到选中的班级信息
  193 + const selectedClass = this.list.find(item => item.id === this.selectedIds[0])
  194 + if (selectedClass) {
  195 + this.addStudentVisible = true
  196 + this.$nextTick(() => {
  197 + this.$refs.AddStudentForm.init(selectedClass.id, selectedClass.className)
  198 + })
  199 + }
  200 + },
  201 +
  202 + // 向班级添加学员
  203 + addStudentsToClass(row) {
  204 + this.addStudentVisible = true
  205 + this.$nextTick(() => {
  206 + this.$refs.AddStudentForm.init(row.id, row.className)
  207 + })
  208 + },
  209 +
  210 + // 查看学员
  211 + viewStudents(row) {
  212 + this.studentListVisible = true
  213 + this.$nextTick(() => {
  214 + this.$refs.StudentListDialog.init(row.id, row.className)
  215 + })
  216 + },
  217 +
  218 + // 查看学习记录
  219 + viewStudyRecords(row) {
  220 + this.studyRecordVisible = true
  221 + this.$nextTick(() => {
  222 + this.$refs.StudyRecordDialog.init(row.id, row.className)
  223 + })
  224 + },
  225 +
  226 + // 多选
  227 + handleSelectionChange(selection) {
  228 + this.selectedIds = selection.map(item => item.id)
  229 + },
  230 +
  231 + // 处理学员列表中的学习记录查看
  232 + handleViewStudyRecords(row) {
  233 + this.studyRecordVisible = true
  234 + this.$nextTick(() => {
  235 + this.$refs.StudyRecordDialog.init(row.classId, row.className)
  236 + })
  237 + },
  238 + }
  239 +}
  240 +</script>
  241 +
  242 +<style scoped>
  243 +.NCC-common-layout {
  244 + height: 100%;
  245 +}
  246 +</style>
... ...
antis-ncc-admin/src/views/lqStudyClass/test.html 0 → 100644
  1 +<!DOCTYPE html>
  2 +<html lang="zh-CN">
  3 +<head>
  4 + <meta charset="UTF-8">
  5 + <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6 + <title>学习班级管理 - 功能测试</title>
  7 + <style>
  8 + body {
  9 + font-family: 'Microsoft YaHei', Arial, sans-serif;
  10 + margin: 0;
  11 + padding: 20px;
  12 + background-color: #f5f7fa;
  13 + }
  14 + .container {
  15 + max-width: 1200px;
  16 + margin: 0 auto;
  17 + background: white;
  18 + border-radius: 8px;
  19 + padding: 30px;
  20 + box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
  21 + }
  22 + .header {
  23 + text-align: center;
  24 + margin-bottom: 30px;
  25 + padding-bottom: 20px;
  26 + border-bottom: 2px solid #409EFF;
  27 + }
  28 + .header h1 {
  29 + color: #409EFF;
  30 + margin: 0;
  31 + font-size: 28px;
  32 + }
  33 + .header p {
  34 + color: #666;
  35 + margin: 10px 0 0 0;
  36 + font-size: 16px;
  37 + }
  38 + .feature-section {
  39 + margin-bottom: 30px;
  40 + }
  41 + .feature-section h2 {
  42 + color: #303133;
  43 + border-left: 4px solid #409EFF;
  44 + padding-left: 15px;
  45 + margin-bottom: 20px;
  46 + }
  47 + .feature-list {
  48 + list-style: none;
  49 + padding: 0;
  50 + }
  51 + .feature-list li {
  52 + padding: 10px 0;
  53 + border-bottom: 1px solid #ebeef5;
  54 + position: relative;
  55 + padding-left: 25px;
  56 + }
  57 + .feature-list li:before {
  58 + content: "✓";
  59 + position: absolute;
  60 + left: 0;
  61 + color: #67C23A;
  62 + font-weight: bold;
  63 + }
  64 + .api-info {
  65 + background: #f8f9fa;
  66 + padding: 20px;
  67 + border-radius: 6px;
  68 + margin: 20px 0;
  69 + }
  70 + .api-info h3 {
  71 + color: #409EFF;
  72 + margin-top: 0;
  73 + }
  74 + .code-block {
  75 + background: #2d3748;
  76 + color: #e2e8f0;
  77 + padding: 15px;
  78 + border-radius: 4px;
  79 + font-family: 'Courier New', monospace;
  80 + font-size: 14px;
  81 + overflow-x: auto;
  82 + margin: 10px 0;
  83 + }
  84 + .file-structure {
  85 + background: #f8f9fa;
  86 + padding: 15px;
  87 + border-radius: 4px;
  88 + font-family: 'Courier New', monospace;
  89 + font-size: 14px;
  90 + margin: 10px 0;
  91 + }
  92 + .status-badge {
  93 + display: inline-block;
  94 + padding: 4px 8px;
  95 + border-radius: 12px;
  96 + font-size: 12px;
  97 + font-weight: bold;
  98 + margin-left: 10px;
  99 + }
  100 + .status-completed {
  101 + background: #f0f9ff;
  102 + color: #27ae60;
  103 + }
  104 + .status-pending {
  105 + background: #fff7e6;
  106 + color: #e6a23c;
  107 + }
  108 + </style>
  109 +</head>
  110 +<body>
  111 + <div class="container">
  112 + <div class="header">
  113 + <h1>🎓 学习班级管理系统</h1>
  114 + <p>基于Vue 2.6 + Element UI + ASP.NET Core开发的学习班级管理功能</p>
  115 + </div>
  116 +
  117 + <div class="feature-section">
  118 + <h2>📋 已实现功能</h2>
  119 + <ul class="feature-list">
  120 + <li>学习班级列表展示(支持分页、搜索、筛选)</li>
  121 + <li>创建学习班级并添加学员(批量添加)</li>
  122 + <li>向现有班级添加学员</li>
  123 + <li>查看班级下所有学员信息(分页展示)</li>
  124 + <li>学习记录管理(添加、查看、作废)</li>
  125 + <li>学员信息搜索和筛选</li>
  126 + <li>学习记录搜索和筛选</li>
  127 + <li>响应式布局设计</li>
  128 + <li>表单验证和错误处理</li>
  129 + </ul>
  130 + </div>
  131 +
  132 + <div class="feature-section">
  133 + <h2>🔧 API接口配置</h2>
  134 + <div class="api-info">
  135 + <h3>接口地址:<code>/api/Extend/LqStudyClass</code></h3>
  136 + <p><strong>请求方法:</strong>GET, POST</p>
  137 + <p><strong>主要接口:</strong></p>
  138 + <div class="code-block">
  139 +POST /api/Extend/LqStudyClass/CreateClassWithStudents
  140 +GET /api/Extend/LqStudyClass/GetClassList
  141 +POST /api/Extend/LqStudyClass/AddStudentsToClass
  142 +GET /api/Extend/LqStudyClass/GetStudentListByClassId
  143 +POST /api/Extend/LqStudyClass/AddStudyRecord
  144 +GET /api/Extend/LqStudyClass/GetStudyRecordList
  145 +POST /api/Extend/LqStudyClass/CancelStudyRecord
  146 + </div>
  147 + </div>
  148 + </div>
  149 +
  150 + <div class="feature-section">
  151 + <h2>📁 文件结构</h2>
  152 + <div class="file-structure">
  153 +lqStudyClass/
  154 +├── index.vue # 主页面组件
  155 +├── CreateClassForm.vue # 创建班级表单组件
  156 +├── AddStudentForm.vue # 添加学员表单组件
  157 +├── StudentListDialog.vue # 学员列表弹窗组件
  158 +└── StudyRecordDialog.vue # 学习记录管理弹窗组件
  159 +
  160 +api/extend/
  161 +└── lqStudyClass.js # API接口定义
  162 + </div>
  163 + </div>
  164 +
  165 + <div class="feature-section">
  166 + <h2>🎯 核心功能说明</h2>
  167 + <div class="api-info">
  168 + <h3>1. 创建学习班级并添加学员</h3>
  169 + <p>支持一次性创建班级并批量添加学员,包含班级基本信息(名称、老师、时间、备注)和学员详细信息(姓名、手机、员工ID、入学时间、HR归属)。</p>
  170 +
  171 + <h3>2. 班级列表管理</h3>
  172 + <p>提供班级列表展示,支持按班级名称、授课老师、开始时间等条件搜索,支持分页显示。</p>
  173 +
  174 + <h3>3. 学员管理</h3>
  175 + <p>可以查看指定班级下的所有学员信息,支持学员信息搜索和筛选,支持向现有班级添加新学员。</p>
  176 +
  177 + <h3>4. 学习记录管理</h3>
  178 + <p>记录学员的学习情况,包括学习类型、交通费、学习日期、日常状态、是否下店协助等信息,支持记录的添加、查看和作废操作。</p>
  179 + </div>
  180 + </div>
  181 +
  182 + <div class="feature-section">
  183 + <h2>🚀 技术特点</h2>
  184 + <ul class="feature-list">
  185 + <li>采用Vue 2.6 + Element UI技术栈</li>
  186 + <li>组件化开发,模块清晰</li>
  187 + <li>统一的API调用方式</li>
  188 + <li>完善的表单验证</li>
  189 + <li>响应式设计</li>
  190 + <li>良好的用户体验</li>
  191 + <li>符合项目开发规范</li>
  192 + </ul>
  193 + </div>
  194 +
  195 + <div class="feature-section">
  196 + <h2>📊 数据流程</h2>
  197 + <div class="api-info">
  198 + <p><strong>创建班级流程:</strong></p>
  199 + <ol>
  200 + <li>填写班级基本信息(名称、老师、时间等)</li>
  201 + <li>添加学员信息(可批量添加)</li>
  202 + <li>提交表单,后端创建班级和学员记录</li>
  203 + <li>返回创建结果,刷新列表</li>
  204 + </ol>
  205 +
  206 + <p><strong>学员管理流程:</strong></p>
  207 + <ol>
  208 + <li>从班级列表选择班级</li>
  209 + <li>查看班级学员列表</li>
  210 + <li>支持搜索和筛选学员</li>
  211 + <li>可添加新学员到班级</li>
  212 + </ol>
  213 +
  214 + <p><strong>学习记录流程:</strong></p>
  215 + <ol>
  216 + <li>选择班级查看学习记录</li>
  217 + <li>添加新的学习记录</li>
  218 + <li>支持记录搜索和筛选</li>
  219 + <li>可作废无效记录</li>
  220 + </ol>
  221 + </div>
  222 + </div>
  223 +
  224 + <div class="feature-section">
  225 + <h2>✅ 开发状态</h2>
  226 + <p>
  227 + <strong>前端页面:</strong><span class="status-badge status-completed">已完成</span>
  228 + <strong>API接口:</strong><span class="status-badge status-completed">已对接</span>
  229 + <strong>路由配置:</strong><span class="status-badge status-completed">已配置</span>
  230 + <strong>功能测试:</strong><span class="status-badge status-pending">待测试</span>
  231 + </p>
  232 + </div>
  233 + </div>
  234 +</body>
  235 +</html>
  236 +
... ...
antis-ncc-admin/src/views/storeTotalPerformanceStatistics/index.vue
... ... @@ -61,6 +61,26 @@
61 61 <el-table-column prop="ItemQuantity" label="品项数量" width="100" align="right"></el-table-column>
62 62 <el-table-column prop="FirstOrderCount" label="首开单数量" width="100" align="right"></el-table-column>
63 63 <el-table-column prop="UpgradeOrderCount" label="升单数量" width="100" align="right"></el-table-column>
  64 + <el-table-column prop="FirstOrderPerformance" label="首单业绩" width="120" align="right">
  65 + <template slot-scope="scope">
  66 + {{ formatMoney(scope.row.FirstOrderPerformance) }}
  67 + </template>
  68 + </el-table-column>
  69 + <el-table-column prop="UpgradeOrderPerformance" label="升单业绩" width="120" align="right">
  70 + <template slot-scope="scope">
  71 + {{ formatMoney(scope.row.UpgradeOrderPerformance) }}
  72 + </template>
  73 + </el-table-column>
  74 + <el-table-column prop="RefundAmount" label="退款业绩" width="120" align="right">
  75 + <template slot-scope="scope">
  76 + <span style="color: #F56C6C;">{{ formatMoney(scope.row.RefundAmount) }}</span>
  77 + </template>
  78 + </el-table-column>
  79 + <el-table-column prop="RefundCount" label="退款次数" width="100" align="right">
  80 + <template slot-scope="scope">
  81 + <span style="color: #F56C6C;">{{ scope.row.RefundCount || 0 }}</span>
  82 + </template>
  83 + </el-table-column>
64 84 <el-table-column prop="CreateTime" label="创建时间" width="150" align="center">
65 85 <template slot-scope="scope">
66 86 {{ formatDateTime(scope.row.CreateTime) }}
... ...
netcore/src/Modularity/Common/NCC.Common/Enum/CommonStatus.cs deleted
1   -using NCC.Dependency;
2   -using System.ComponentModel;
3   -
4   -namespace NCC.Common.Enum
5   -{
6   - /// <summary>
7   - /// 公共状态
8   - /// </summary>
9   - [SuppressSniffer]
10   - public enum CommonStatus
11   - {
12   - /// <summary>
13   - /// 正常
14   - /// </summary>
15   - [Description("正常")]
16   - ENABLE = 0,
17   -
18   - /// <summary>
19   - /// 停用
20   - /// </summary>
21   - [Description("停用")]
22   - DISABLE = 1,
23   -
24   - /// <summary>
25   - /// 删除
26   - /// </summary>
27   - [Description("删除")]
28   - DELETED = 2
29   - }
30   -}
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqCardTransferLog/LqCardTransferLogCrInput.cs 0 → 100644
  1 +using System;
  2 +using System.ComponentModel.DataAnnotations;
  3 +
  4 +namespace NCC.Extend.Entitys.Dto.LqCardTransferLog
  5 +{
  6 + /// <summary>
  7 + /// 转卡日志创建输入参数
  8 + /// </summary>
  9 + public class LqCardTransferLogCrInput
  10 + {
  11 + /// <summary>
  12 + /// 退卡ID
  13 + /// </summary>
  14 + [Required(ErrorMessage = "退卡ID不能为空")]
  15 + public string refundCardId { get; set; }
  16 +
  17 + /// <summary>
  18 + /// 开卡ID
  19 + /// </summary>
  20 + [Required(ErrorMessage = "开卡ID不能为空")]
  21 + public string billingCardId { get; set; }
  22 +
  23 + /// <summary>
  24 + /// 转卡人会员ID
  25 + /// </summary>
  26 + [Required(ErrorMessage = "转卡人会员ID不能为空")]
  27 + public string transferFromMemberId { get; set; }
  28 +
  29 + /// <summary>
  30 + /// 被转卡人会员ID
  31 + /// </summary>
  32 + [Required(ErrorMessage = "被转卡人会员ID不能为空")]
  33 + public string transferToMemberId { get; set; }
  34 +
  35 + /// <summary>
  36 + /// 转卡总金额
  37 + /// </summary>
  38 + [Required(ErrorMessage = "转卡总金额不能为空")]
  39 + [Range(0.01, double.MaxValue, ErrorMessage = "转卡总金额必须大于0")]
  40 + public decimal transferAmount { get; set; }
  41 +
  42 + /// <summary>
  43 + /// 转卡时间
  44 + /// </summary>
  45 + [Required(ErrorMessage = "转卡时间不能为空")]
  46 + public DateTime transferTime { get; set; }
  47 +
  48 + /// <summary>
  49 + /// 操作人ID
  50 + /// </summary>
  51 + [Required(ErrorMessage = "操作人ID不能为空")]
  52 + public string operatorId { get; set; }
  53 +
  54 + /// <summary>
  55 + /// 备注信息
  56 + /// </summary>
  57 + public string remarks { get; set; }
  58 + }
  59 +}
... ...
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqCardTransferLog/LqCardTransferLogInfoOutput.cs 0 → 100644
  1 +using System;
  2 +
  3 +namespace NCC.Extend.Entitys.Dto.LqCardTransferLog
  4 +{
  5 + /// <summary>
  6 + /// 转卡日志详情输出参数
  7 + /// </summary>
  8 + public class LqCardTransferLogInfoOutput
  9 + {
  10 + /// <summary>
  11 + /// 主键ID
  12 + /// </summary>
  13 + public string id { get; set; }
  14 +
  15 + /// <summary>
  16 + /// 退卡ID
  17 + /// </summary>
  18 + public string refundCardId { get; set; }
  19 +
  20 + /// <summary>
  21 + /// 开卡ID
  22 + /// </summary>
  23 + public string billingCardId { get; set; }
  24 +
  25 + /// <summary>
  26 + /// 转卡人会员ID
  27 + /// </summary>
  28 + public string transferFromMemberId { get; set; }
  29 +
  30 + /// <summary>
  31 + /// 转卡人姓名
  32 + /// </summary>
  33 + public string transferFromMemberName { get; set; }
  34 +
  35 + /// <summary>
  36 + /// 被转卡人会员ID
  37 + /// </summary>
  38 + public string transferToMemberId { get; set; }
  39 +
  40 + /// <summary>
  41 + /// 被转卡人姓名
  42 + /// </summary>
  43 + public string transferToMemberName { get; set; }
  44 +
  45 + /// <summary>
  46 + /// 转卡总金额
  47 + /// </summary>
  48 + public decimal transferAmount { get; set; }
  49 +
  50 + /// <summary>
  51 + /// 转卡时间
  52 + /// </summary>
  53 + public DateTime transferTime { get; set; }
  54 +
  55 + /// <summary>
  56 + /// 操作人ID
  57 + /// </summary>
  58 + public string operatorId { get; set; }
  59 +
  60 + /// <summary>
  61 + /// 备注信息
  62 + /// </summary>
  63 + public string remarks { get; set; }
  64 +
  65 + /// <summary>
  66 + /// 创建时间
  67 + /// </summary>
  68 + public DateTime? createTime { get; set; }
  69 +
  70 + /// <summary>
  71 + /// 更新时间
  72 + /// </summary>
  73 + public DateTime? updateTime { get; set; }
  74 +
  75 + /// <summary>
  76 + /// 是否有效
  77 + /// </summary>
  78 + public int isEffective { get; set; }
  79 + }
  80 +}
... ...
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqCardTransferLog/LqCardTransferLogListOutput.cs 0 → 100644
  1 +using System;
  2 +
  3 +namespace NCC.Extend.Entitys.Dto.LqCardTransferLog
  4 +{
  5 + /// <summary>
  6 + /// 转卡日志列表输出参数
  7 + /// </summary>
  8 + public class LqCardTransferLogListOutput
  9 + {
  10 + /// <summary>
  11 + /// 主键ID
  12 + /// </summary>
  13 + public string id { get; set; }
  14 +
  15 + /// <summary>
  16 + /// 退卡ID
  17 + /// </summary>
  18 + public string refundCardId { get; set; }
  19 +
  20 + /// <summary>
  21 + /// 开卡ID
  22 + /// </summary>
  23 + public string billingCardId { get; set; }
  24 +
  25 + /// <summary>
  26 + /// 转卡人会员ID
  27 + /// </summary>
  28 + public string transferFromMemberId { get; set; }
  29 +
  30 + /// <summary>
  31 + /// 转卡人姓名
  32 + /// </summary>
  33 + public string transferFromMemberName { get; set; }
  34 +
  35 + /// <summary>
  36 + /// 被转卡人会员ID
  37 + /// </summary>
  38 + public string transferToMemberId { get; set; }
  39 +
  40 + /// <summary>
  41 + /// 被转卡人姓名
  42 + /// </summary>
  43 + public string transferToMemberName { get; set; }
  44 +
  45 + /// <summary>
  46 + /// 转卡总金额
  47 + /// </summary>
  48 + public decimal transferAmount { get; set; }
  49 +
  50 + /// <summary>
  51 + /// 转卡时间
  52 + /// </summary>
  53 + public DateTime transferTime { get; set; }
  54 +
  55 + /// <summary>
  56 + /// 操作人ID
  57 + /// </summary>
  58 + public string operatorId { get; set; }
  59 +
  60 + /// <summary>
  61 + /// 备注信息
  62 + /// </summary>
  63 + public string remarks { get; set; }
  64 +
  65 + /// <summary>
  66 + /// 创建时间
  67 + /// </summary>
  68 + public DateTime? createTime { get; set; }
  69 +
  70 + /// <summary>
  71 + /// 更新时间
  72 + /// </summary>
  73 + public DateTime? updateTime { get; set; }
  74 +
  75 + /// <summary>
  76 + /// 是否有效
  77 + /// </summary>
  78 + public int isEffective { get; set; }
  79 + }
  80 +}
... ...
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqCardTransferLog/LqCardTransferLogListQueryInput.cs 0 → 100644
  1 +using System;
  2 +using NCC.Common.Filter;
  3 +
  4 +namespace NCC.Extend.Entitys.Dto.LqCardTransferLog
  5 +{
  6 + /// <summary>
  7 + /// 转卡日志列表查询输入参数
  8 + /// </summary>
  9 + public class LqCardTransferLogListQueryInput : PageInputBase
  10 + {
  11 + /// <summary>
  12 + /// 转卡人会员ID
  13 + /// </summary>
  14 + public string transferFromMemberId { get; set; }
  15 +
  16 + /// <summary>
  17 + /// 被转卡人会员ID
  18 + /// </summary>
  19 + public string transferToMemberId { get; set; }
  20 +
  21 + /// <summary>
  22 + /// 操作人ID
  23 + /// </summary>
  24 + public string operatorId { get; set; }
  25 +
  26 + /// <summary>
  27 + /// 是否有效(1:有效 0:无效)
  28 + /// </summary>
  29 + public int isEffective { get; set; } = 1;
  30 +
  31 + /// <summary>
  32 + /// 转卡开始时间
  33 + /// </summary>
  34 + public DateTime? transferStartTime { get; set; }
  35 +
  36 + /// <summary>
  37 + /// 转卡结束时间
  38 + /// </summary>
  39 + public DateTime? transferEndTime { get; set; }
  40 +
  41 + /// <summary>
  42 + /// 最小转卡金额
  43 + /// </summary>
  44 + public decimal? minTransferAmount { get; set; }
  45 +
  46 + /// <summary>
  47 + /// 最大转卡金额
  48 + /// </summary>
  49 + public decimal? maxTransferAmount { get; set; }
  50 + }
  51 +}
... ...
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqHytkHytk/LqHytkHytkCrInput.cs
... ... @@ -57,6 +57,11 @@ namespace NCC.Extend.Entitys.Dto.LqHytkHytk
57 57 public decimal? tkje { get; set; }
58 58  
59 59 /// <summary>
  60 + /// 实退金额
  61 + /// </summary>
  62 + public decimal? actualRefundAmount { get; set; }
  63 +
  64 + /// <summary>
60 65 /// 手工费用
61 66 /// </summary>
62 67 public decimal? sgfy { get; set; }
... ...
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqHytkHytk/LqHytkHytkInfoOutput.cs
... ... @@ -57,6 +57,11 @@ namespace NCC.Extend.Entitys.Dto.LqHytkHytk
57 57 public decimal? tkje { get; set; }
58 58  
59 59 /// <summary>
  60 + /// 实退金额
  61 + /// </summary>
  62 + public decimal? actualRefundAmount { get; set; }
  63 +
  64 + /// <summary>
60 65 /// 手工费用
61 66 /// </summary>
62 67 public decimal? sgfy { get; set; }
... ...
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqHytkHytk/LqHytkHytkListOutput.cs
... ... @@ -53,6 +53,11 @@ namespace NCC.Extend.Entitys.Dto.LqHytkHytk
53 53 public decimal? tkje { get; set; }
54 54  
55 55 /// <summary>
  56 + /// 实退金额
  57 + /// </summary>
  58 + public decimal? actualRefundAmount { get; set; }
  59 +
  60 + /// <summary>
56 61 /// 手工费用
57 62 /// </summary>
58 63 public decimal? sgfy { get; set; }
... ...
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqHytkHytk/LqHytkHytkListQueryInput.cs
... ... @@ -12,72 +12,72 @@ namespace NCC.Extend.Entitys.Dto.LqHytkHytk
12 12 /// 退卡编号
13 13 /// </summary>
14 14 public string id { get; set; }
15   -
  15 +
16 16 /// <summary>
17 17 /// 门店
18 18 /// </summary>
19 19 public string md { get; set; }
20   -
  20 +
21 21 /// <summary>
22 22 /// 门店编号
23 23 /// </summary>
24 24 public string mdbh { get; set; }
25   -
  25 +
26 26 /// <summary>
27 27 /// 门店名称
28 28 /// </summary>
29 29 public string mdmc { get; set; }
30   -
  30 +
31 31 /// <summary>
32 32 /// 会员
33 33 /// </summary>
34 34 public string hy { get; set; }
35   -
  35 +
36 36 /// <summary>
37 37 /// 会员姓名
38 38 /// </summary>
39 39 public string hymc { get; set; }
40   -
  40 +
41 41 /// <summary>
42 42 /// 会员账号
43 43 /// </summary>
44 44 public string hyzh { get; set; }
45   -
  45 +
46 46 /// <summary>
47 47 /// 顾客类型
48 48 /// </summary>
49 49 public string gklx { get; set; }
50   -
  50 +
51 51 /// <summary>
52 52 /// 退卡总金额
53 53 /// </summary>
54 54 public decimal? tkje { get; set; }
55   -
  55 +
56 56 /// <summary>
57 57 /// 手工费用
58 58 /// </summary>
59 59 public decimal? sgfy { get; set; }
60   -
  60 +
61 61 /// <summary>
62 62 /// 备注
63 63 /// </summary>
64 64 public string bz { get; set; }
65   -
  65 +
66 66 /// <summary>
67 67 /// 退卡时间
68 68 /// </summary>
69 69 public string tksj { get; set; }
70   -
  70 +
71 71 /// <summary>
72 72 /// 操作人员
73 73 /// </summary>
74 74 public string czry { get; set; }
75   -
  75 +
76 76 /// <summary>
77 77 /// 退卡状态
78 78 /// </summary>
79 79 public string tkzt { get; set; }
80   -
  80 +
81 81 /// <summary>
82 82 /// 退卡原因
83 83 /// </summary>
... ... @@ -87,6 +87,11 @@ namespace NCC.Extend.Entitys.Dto.LqHytkHytk
87 87 /// 退卡附件
88 88 /// </summary>
89 89 public string fileUrl { get; set; }
90   -
  90 +
  91 + /// <summary>
  92 + /// 是否有效
  93 + /// </summary>
  94 + public int isEffective { get; set; } = 0;
  95 +
91 96 }
92 97 }
93 98 \ No newline at end of file
... ...
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqHytkHytk/LqHytkHytkUpInput.cs
... ... @@ -57,6 +57,11 @@ namespace NCC.Extend.Entitys.Dto.LqHytkHytk
57 57 public decimal? tkje { get; set; }
58 58  
59 59 /// <summary>
  60 + /// 实退金额
  61 + /// </summary>
  62 + public decimal? actualRefundAmount { get; set; }
  63 +
  64 + /// <summary>
60 65 /// 手工费用
61 66 /// </summary>
62 67 public decimal? sgfy { get; set; }
... ...
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqInventory/LqInventoryCrInput.cs 0 → 100644
  1 +using System;
  2 +using System.ComponentModel.DataAnnotations;
  3 +
  4 +namespace NCC.Extend.Entitys.Dto.LqInventory
  5 +{
  6 + /// <summary>
  7 + /// 库存创建输入
  8 + /// </summary>
  9 + public class LqInventoryCrInput
  10 + {
  11 + /// <summary>
  12 + /// 产品名称
  13 + /// </summary>
  14 + [Required(ErrorMessage = "产品名称不能为空")]
  15 + [StringLength(100, ErrorMessage = "产品名称长度不能超过100个字符")]
  16 + [Display(Name = "产品名称")]
  17 + public string ProductName { get; set; }
  18 +
  19 + /// <summary>
  20 + /// 价格
  21 + /// </summary>
  22 + [Required(ErrorMessage = "价格不能为空")]
  23 + [Range(0, double.MaxValue, ErrorMessage = "价格不能小于0")]
  24 + [Display(Name = "价格")]
  25 + public decimal Price { get; set; }
  26 +
  27 + /// <summary>
  28 + /// 数量
  29 + /// </summary>
  30 + [Range(0, int.MaxValue, ErrorMessage = "数量不能小于0")]
  31 + [Display(Name = "数量")]
  32 + public int Quantity { get; set; } = 0;
  33 +
  34 + /// <summary>
  35 + /// 产品类别
  36 + /// </summary>
  37 + [Required(ErrorMessage = "产品类别不能为空")]
  38 + [StringLength(50, ErrorMessage = "产品类别长度不能超过50个字符")]
  39 + [Display(Name = "产品类别")]
  40 + public string ProductCategory { get; set; }
  41 +
  42 + /// <summary>
  43 + /// 归属部门ID
  44 + /// </summary>
  45 + [Required(ErrorMessage = "归属部门ID不能为空")]
  46 + [StringLength(50, ErrorMessage = "归属部门ID长度不能超过50个字符")]
  47 + [Display(Name = "归属部门ID")]
  48 + public string DepartmentId { get; set; }
  49 +
  50 + /// <summary>
  51 + /// 标准单位
  52 + /// </summary>
  53 + [Required(ErrorMessage = "标准单位不能为空")]
  54 + [StringLength(20, ErrorMessage = "标准单位长度不能超过20个字符")]
  55 + [Display(Name = "标准单位")]
  56 + public string StandardUnit { get; set; }
  57 + }
  58 +}
... ...
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqInventory/LqInventoryInfoOutput.cs 0 → 100644
  1 +using System;
  2 +using System.ComponentModel.DataAnnotations;
  3 +
  4 +namespace NCC.Extend.Entitys.Dto.LqInventory
  5 +{
  6 + /// <summary>
  7 + /// 库存详情输出
  8 + /// </summary>
  9 + public class LqInventoryInfoOutput : LqInventoryListOutput
  10 + {
  11 + // 继承自LqInventoryListOutput,包含所有列表输出字段
  12 + // 可以根据需要添加额外的详情字段
  13 + }
  14 +}
0 15 \ No newline at end of file
... ...
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqInventory/LqInventoryListOutput.cs 0 → 100644
  1 +using System;
  2 +using System.ComponentModel.DataAnnotations;
  3 +
  4 +namespace NCC.Extend.Entitys.Dto.LqInventory
  5 +{
  6 + /// <summary>
  7 + /// 库存列表输出
  8 + /// </summary>
  9 + public class LqInventoryListOutput
  10 + {
  11 + /// <summary>
  12 + /// 库存ID
  13 + /// </summary>
  14 + [Display(Name = "库存ID")]
  15 + public string id { get; set; }
  16 +
  17 + /// <summary>
  18 + /// 产品名称
  19 + /// </summary>
  20 + [Display(Name = "产品名称")]
  21 + public string productName { get; set; }
  22 +
  23 + /// <summary>
  24 + /// 价格
  25 + /// </summary>
  26 + [Display(Name = "价格")]
  27 + public decimal price { get; set; }
  28 +
  29 + /// <summary>
  30 + /// 数量
  31 + /// </summary>
  32 + [Display(Name = "数量")]
  33 + public int quantity { get; set; }
  34 +
  35 + /// <summary>
  36 + /// 产品类别
  37 + /// </summary>
  38 + [Display(Name = "产品类别")]
  39 + public string productCategory { get; set; }
  40 +
  41 + /// <summary>
  42 + /// 归属部门ID
  43 + /// </summary>
  44 + [Display(Name = "归属部门ID")]
  45 + public string departmentId { get; set; }
  46 +
  47 + /// <summary>
  48 + /// 部门名称
  49 + /// </summary>
  50 + [Display(Name = "部门名称")]
  51 + public string departmentName { get; set; }
  52 +
  53 + /// <summary>
  54 + /// 标准单位
  55 + /// </summary>
  56 + [Display(Name = "标准单位")]
  57 + public string standardUnit { get; set; }
  58 +
  59 + /// <summary>
  60 + /// 总价值
  61 + /// </summary>
  62 + [Display(Name = "总价值")]
  63 + public decimal totalValue { get; set; }
  64 +
  65 + /// <summary>
  66 + /// 创建人ID
  67 + /// </summary>
  68 + [Display(Name = "创建人ID")]
  69 + public string createUser { get; set; }
  70 +
  71 + /// <summary>
  72 + /// 创建人姓名
  73 + /// </summary>
  74 + [Display(Name = "创建人姓名")]
  75 + public string createUserName { get; set; }
  76 +
  77 + /// <summary>
  78 + /// 创建时间
  79 + /// </summary>
  80 + [Display(Name = "创建时间")]
  81 + public DateTime createTime { get; set; }
  82 +
  83 + /// <summary>
  84 + /// 更新人ID
  85 + /// </summary>
  86 + [Display(Name = "更新人ID")]
  87 + public string updateUser { get; set; }
  88 +
  89 + /// <summary>
  90 + /// 更新人姓名
  91 + /// </summary>
  92 + [Display(Name = "更新人姓名")]
  93 + public string updateUserName { get; set; }
  94 +
  95 + /// <summary>
  96 + /// 更新时间
  97 + /// </summary>
  98 + [Display(Name = "更新时间")]
  99 + public DateTime? updateTime { get; set; }
  100 +
  101 + /// <summary>
  102 + /// 是否有效
  103 + /// </summary>
  104 + [Display(Name = "是否有效")]
  105 + public int isEffective { get; set; }
  106 + }
  107 +}
0 108 \ No newline at end of file
... ...
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqInventory/LqInventoryListQueryInput.cs 0 → 100644
  1 +using NCC.Common.Filter;
  2 +using System;
  3 +using System.ComponentModel.DataAnnotations;
  4 +
  5 +namespace NCC.Extend.Entitys.Dto.LqInventory
  6 +{
  7 + /// <summary>
  8 + /// 库存列表查询输入
  9 + /// </summary>
  10 + public class LqInventoryListQueryInput : PageInputBase
  11 + {
  12 + /// <summary>
  13 + /// 产品名称
  14 + /// </summary>
  15 + [Display(Name = "产品名称", Description = "根据产品名称筛选")]
  16 + public string ProductName { get; set; }
  17 +
  18 + /// <summary>
  19 + /// 产品类别
  20 + /// </summary>
  21 + [Display(Name = "产品类别", Description = "根据产品类别筛选")]
  22 + public string ProductCategory { get; set; }
  23 +
  24 + /// <summary>
  25 + /// 归属部门ID
  26 + /// </summary>
  27 + [Display(Name = "归属部门ID", Description = "根据归属部门ID筛选")]
  28 + public string DepartmentId { get; set; }
  29 +
  30 + /// <summary>
  31 + /// 价格最小值
  32 + /// </summary>
  33 + [Display(Name = "价格最小值", Description = "价格范围的最小值")]
  34 + public decimal? PriceMin { get; set; }
  35 +
  36 + /// <summary>
  37 + /// 价格最大值
  38 + /// </summary>
  39 + [Display(Name = "价格最大值", Description = "价格范围的最大值")]
  40 + public decimal? PriceMax { get; set; }
  41 +
  42 + /// <summary>
  43 + /// 数量最小值
  44 + /// </summary>
  45 + [Display(Name = "数量最小值", Description = "数量范围的最小值")]
  46 + public int? QuantityMin { get; set; }
  47 +
  48 + /// <summary>
  49 + /// 数量最大值
  50 + /// </summary>
  51 + [Display(Name = "数量最大值", Description = "数量范围的最大值")]
  52 + public int? QuantityMax { get; set; }
  53 +
  54 + /// <summary>
  55 + /// 是否有效
  56 + /// </summary>
  57 + [Display(Name = "是否有效", Description = "根据是否有效筛选")]
  58 + public int? IsEffective { get; set; }
  59 + }
  60 +}
0 61 \ No newline at end of file
... ...
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqInventory/LqInventoryUpInput.cs 0 → 100644
  1 +using System;
  2 +using System.ComponentModel.DataAnnotations;
  3 +
  4 +namespace NCC.Extend.Entitys.Dto.LqInventory
  5 +{
  6 + /// <summary>
  7 + /// 库存更新输入
  8 + /// </summary>
  9 + public class LqInventoryUpInput : LqInventoryCrInput
  10 + {
  11 + /// <summary>
  12 + /// 库存ID
  13 + /// </summary>
  14 + [Required(ErrorMessage = "库存ID不能为空")]
  15 + [StringLength(50, ErrorMessage = "库存ID长度不能超过50个字符")]
  16 + [Display(Name = "库存ID")]
  17 + public string Id { get; set; }
  18 + }
  19 +}
... ...
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqInventoryUsage/LqInventoryUsageCrInput.cs 0 → 100644
  1 +using System;
  2 +using System.ComponentModel.DataAnnotations;
  3 +
  4 +namespace NCC.Extend.Entitys.Dto.LqInventoryUsage
  5 +{
  6 + /// <summary>
  7 + /// 库存使用记录创建输入
  8 + /// </summary>
  9 + public class LqInventoryUsageCrInput
  10 + {
  11 + /// <summary>
  12 + /// 产品ID
  13 + /// </summary>
  14 + [Required(ErrorMessage = "产品ID不能为空")]
  15 + [StringLength(50, ErrorMessage = "产品ID长度不能超过50个字符")]
  16 + [Display(Name = "产品ID")]
  17 + public string ProductId { get; set; }
  18 +
  19 + /// <summary>
  20 + /// 门店ID
  21 + /// </summary>
  22 + [Required(ErrorMessage = "门店ID不能为空")]
  23 + [StringLength(50, ErrorMessage = "门店ID长度不能超过50个字符")]
  24 + [Display(Name = "门店ID")]
  25 + public string StoreId { get; set; }
  26 +
  27 + /// <summary>
  28 + /// 使用时间
  29 + /// </summary>
  30 + [Required(ErrorMessage = "使用时间不能为空")]
  31 + [Display(Name = "使用时间")]
  32 + public DateTime UsageTime { get; set; }
  33 +
  34 + /// <summary>
  35 + /// 使用数量
  36 + /// </summary>
  37 + [Required(ErrorMessage = "使用数量不能为空")]
  38 + [Range(1, int.MaxValue, ErrorMessage = "使用数量必须大于0")]
  39 + [Display(Name = "使用数量")]
  40 + public int UsageQuantity { get; set; }
  41 +
  42 + /// <summary>
  43 + /// 关联消耗ID
  44 + /// </summary>
  45 + [StringLength(50, ErrorMessage = "关联消耗ID长度不能超过50个字符")]
  46 + [Display(Name = "关联消耗ID")]
  47 + public string RelatedConsumeId { get; set; }
  48 + }
  49 +}
... ...
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqInventoryUsage/LqInventoryUsageInfoOutput.cs 0 → 100644
  1 +using System;
  2 +
  3 +namespace NCC.Extend.Entitys.Dto.LqInventoryUsage
  4 +{
  5 + /// <summary>
  6 + /// 库存使用记录详情输出
  7 + /// </summary>
  8 + public class LqInventoryUsageInfoOutput
  9 + {
  10 + /// <summary>
  11 + /// 使用记录ID
  12 + /// </summary>
  13 + public string Id { get; set; }
  14 +
  15 + /// <summary>
  16 + /// 产品ID
  17 + /// </summary>
  18 + public string ProductId { get; set; }
  19 +
  20 + /// <summary>
  21 + /// 产品名称
  22 + /// </summary>
  23 + public string ProductName { get; set; }
  24 +
  25 + /// <summary>
  26 + /// 产品类别
  27 + /// </summary>
  28 + public string ProductCategory { get; set; }
  29 +
  30 + /// <summary>
  31 + /// 产品价格
  32 + /// </summary>
  33 + public decimal ProductPrice { get; set; }
  34 +
  35 + /// <summary>
  36 + /// 产品标准单位
  37 + /// </summary>
  38 + public string ProductStandardUnit { get; set; }
  39 +
  40 + /// <summary>
  41 + /// 门店ID
  42 + /// </summary>
  43 + public string StoreId { get; set; }
  44 +
  45 + /// <summary>
  46 + /// 门店名称
  47 + /// </summary>
  48 + public string StoreName { get; set; }
  49 +
  50 + /// <summary>
  51 + /// 使用时间
  52 + /// </summary>
  53 + public DateTime UsageTime { get; set; }
  54 +
  55 + /// <summary>
  56 + /// 使用数量
  57 + /// </summary>
  58 + public int UsageQuantity { get; set; }
  59 +
  60 + /// <summary>
  61 + /// 关联消耗ID
  62 + /// </summary>
  63 + public string RelatedConsumeId { get; set; }
  64 +
  65 + /// <summary>
  66 + /// 创建人ID
  67 + /// </summary>
  68 + public string CreateUser { get; set; }
  69 +
  70 + /// <summary>
  71 + /// 创建人姓名
  72 + /// </summary>
  73 + public string CreateUserName { get; set; }
  74 +
  75 + /// <summary>
  76 + /// 创建时间
  77 + /// </summary>
  78 + public DateTime CreateTime { get; set; }
  79 +
  80 + /// <summary>
  81 + /// 更新人ID
  82 + /// </summary>
  83 + public string UpdateUser { get; set; }
  84 +
  85 + /// <summary>
  86 + /// 更新人姓名
  87 + /// </summary>
  88 + public string UpdateUserName { get; set; }
  89 +
  90 + /// <summary>
  91 + /// 更新时间
  92 + /// </summary>
  93 + public DateTime? UpdateTime { get; set; }
  94 +
  95 + /// <summary>
  96 + /// 是否有效(1:有效 0:无效)
  97 + /// </summary>
  98 + public int IsEffective { get; set; }
  99 +
  100 + /// <summary>
  101 + /// 使用总价值
  102 + /// </summary>
  103 + public decimal UsageTotalValue { get; set; }
  104 + }
  105 +}
... ...
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqInventoryUsage/LqInventoryUsageListOutput.cs 0 → 100644
  1 +using System;
  2 +
  3 +namespace NCC.Extend.Entitys.Dto.LqInventoryUsage
  4 +{
  5 + /// <summary>
  6 + /// 库存使用记录列表输出
  7 + /// </summary>
  8 + public class LqInventoryUsageListOutput
  9 + {
  10 + /// <summary>
  11 + /// 使用记录ID
  12 + /// </summary>
  13 + public string Id { get; set; }
  14 +
  15 + /// <summary>
  16 + /// 产品ID
  17 + /// </summary>
  18 + public string ProductId { get; set; }
  19 +
  20 + /// <summary>
  21 + /// 产品名称
  22 + /// </summary>
  23 + public string ProductName { get; set; }
  24 +
  25 + /// <summary>
  26 + /// 产品类别
  27 + /// </summary>
  28 + public string ProductCategory { get; set; }
  29 +
  30 + /// <summary>
  31 + /// 产品价格
  32 + /// </summary>
  33 + public decimal ProductPrice { 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 DateTime UsageTime { get; set; }
  49 +
  50 + /// <summary>
  51 + /// 使用数量
  52 + /// </summary>
  53 + public int UsageQuantity { get; set; }
  54 +
  55 + /// <summary>
  56 + /// 关联消耗ID
  57 + /// </summary>
  58 + public string RelatedConsumeId { get; set; }
  59 +
  60 + /// <summary>
  61 + /// 创建人ID
  62 + /// </summary>
  63 + public string CreateUser { get; set; }
  64 +
  65 + /// <summary>
  66 + /// 创建人姓名
  67 + /// </summary>
  68 + public string CreateUserName { get; set; }
  69 +
  70 + /// <summary>
  71 + /// 创建时间
  72 + /// </summary>
  73 + public DateTime CreateTime { get; set; }
  74 +
  75 + /// <summary>
  76 + /// 更新人ID
  77 + /// </summary>
  78 + public string UpdateUser { get; set; }
  79 +
  80 + /// <summary>
  81 + /// 更新人姓名
  82 + /// </summary>
  83 + public string UpdateUserName { get; set; }
  84 +
  85 + /// <summary>
  86 + /// 更新时间
  87 + /// </summary>
  88 + public DateTime? UpdateTime { get; set; }
  89 +
  90 + /// <summary>
  91 + /// 是否有效(1:有效 0:无效)
  92 + /// </summary>
  93 + public int IsEffective { get; set; }
  94 +
  95 + /// <summary>
  96 + /// 使用总价值
  97 + /// </summary>
  98 + public decimal UsageTotalValue { get; set; }
  99 + }
  100 +}
... ...
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqInventoryUsage/LqInventoryUsageListQueryInput.cs 0 → 100644
  1 +using NCC.Common.Filter;
  2 +
  3 +namespace NCC.Extend.Entitys.Dto.LqInventoryUsage
  4 +{
  5 + /// <summary>
  6 + /// 库存使用记录列表查询输入
  7 + /// </summary>
  8 + public class LqInventoryUsageListQueryInput : PageInputBase
  9 + {
  10 + /// <summary>
  11 + /// 产品ID
  12 + /// </summary>
  13 + public string ProductId { get; set; }
  14 +
  15 + /// <summary>
  16 + /// 产品名称
  17 + /// </summary>
  18 + public string ProductName { get; set; }
  19 +
  20 + /// <summary>
  21 + /// 产品类别
  22 + /// </summary>
  23 + public string ProductCategory { 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 + /// <summary>
  36 + /// 使用开始时间
  37 + /// </summary>
  38 + public System.DateTime? UsageStartTime { get; set; }
  39 +
  40 + /// <summary>
  41 + /// 使用结束时间
  42 + /// </summary>
  43 + public System.DateTime? UsageEndTime { get; set; }
  44 +
  45 + /// <summary>
  46 + /// 关联消耗ID
  47 + /// </summary>
  48 + public string RelatedConsumeId { get; set; }
  49 +
  50 + /// <summary>
  51 + /// 是否有效
  52 + /// </summary>
  53 + public int? IsEffective { get; set; }
  54 + }
  55 +}
... ...
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqInventoryUsage/LqInventoryUsageStatisticsInput.cs 0 → 100644
  1 +using System;
  2 +using System.ComponentModel.DataAnnotations;
  3 +
  4 +namespace NCC.Extend.Entitys.Dto.LqInventoryUsage
  5 +{
  6 + /// <summary>
  7 + /// 库存使用记录统计查询输入
  8 + /// </summary>
  9 + public class LqInventoryUsageStatisticsInput
  10 + {
  11 + /// <summary>
  12 + /// 开始时间
  13 + /// </summary>
  14 + [Required(ErrorMessage = "开始时间不能为空")]
  15 + [Display(Name = "开始时间")]
  16 + public DateTime StartTime { get; set; }
  17 +
  18 + /// <summary>
  19 + /// 结束时间
  20 + /// </summary>
  21 + [Required(ErrorMessage = "结束时间不能为空")]
  22 + [Display(Name = "结束时间")]
  23 + public DateTime EndTime { get; set; }
  24 +
  25 + /// <summary>
  26 + /// 产品ID(可选,用于筛选特定产品)
  27 + /// </summary>
  28 + [StringLength(50, ErrorMessage = "产品ID长度不能超过50个字符")]
  29 + [Display(Name = "产品ID")]
  30 + public string ProductId { get; set; }
  31 +
  32 + /// <summary>
  33 + /// 门店ID(可选,用于筛选特定门店)
  34 + /// </summary>
  35 + [StringLength(50, ErrorMessage = "门店ID长度不能超过50个字符")]
  36 + [Display(Name = "门店ID")]
  37 + public string StoreId { get; set; }
  38 +
  39 + /// <summary>
  40 + /// 产品类别(可选,用于筛选特定类别)
  41 + /// </summary>
  42 + [StringLength(50, ErrorMessage = "产品类别长度不能超过50个字符")]
  43 + [Display(Name = "产品类别")]
  44 + public string ProductCategory { get; set; }
  45 +
  46 + /// <summary>
  47 + /// 统计类型(日/周/月)
  48 + /// </summary>
  49 + [StringLength(10, ErrorMessage = "统计类型长度不能超过10个字符")]
  50 + [Display(Name = "统计类型")]
  51 + public string StatisticsType { get; set; } = "日";
  52 +
  53 + /// <summary>
  54 + /// 排行榜数量(默认10)
  55 + /// </summary>
  56 + [Range(1, 100, ErrorMessage = "排行榜数量必须在1-100之间")]
  57 + [Display(Name = "排行榜数量")]
  58 + public int RankingCount { get; set; } = 10;
  59 + }
  60 +}
... ...
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqInventoryUsage/LqInventoryUsageStatisticsOutput.cs 0 → 100644
  1 +using System;
  2 +
  3 +namespace NCC.Extend.Entitys.Dto.LqInventoryUsage
  4 +{
  5 + /// <summary>
  6 + /// 产品使用统计输出
  7 + /// </summary>
  8 + public class ProductUsageStatisticsOutput
  9 + {
  10 + /// <summary>
  11 + /// 产品ID
  12 + /// </summary>
  13 + public string ProductId { get; set; }
  14 +
  15 + /// <summary>
  16 + /// 产品名称
  17 + /// </summary>
  18 + public string ProductName { get; set; }
  19 +
  20 + /// <summary>
  21 + /// 产品类别
  22 + /// </summary>
  23 + public string ProductCategory { get; set; }
  24 +
  25 + /// <summary>
  26 + /// 产品价格
  27 + /// </summary>
  28 + public decimal ProductPrice { get; set; }
  29 +
  30 + /// <summary>
  31 + /// 使用总数量
  32 + /// </summary>
  33 + public int TotalUsageQuantity { get; set; }
  34 +
  35 + /// <summary>
  36 + /// 使用总金额
  37 + /// </summary>
  38 + public decimal TotalUsageAmount { get; set; }
  39 +
  40 + /// <summary>
  41 + /// 使用次数
  42 + /// </summary>
  43 + public int UsageCount { get; set; }
  44 +
  45 + /// <summary>
  46 + /// 平均每次使用数量
  47 + /// </summary>
  48 + public decimal AverageUsageQuantity { get; set; }
  49 + }
  50 +
  51 + /// <summary>
  52 + /// 门店使用统计输出
  53 + /// </summary>
  54 + public class StoreUsageStatisticsOutput
  55 + {
  56 + /// <summary>
  57 + /// 门店ID
  58 + /// </summary>
  59 + public string StoreId { get; set; }
  60 +
  61 + /// <summary>
  62 + /// 门店名称
  63 + /// </summary>
  64 + public string StoreName { get; set; }
  65 +
  66 + /// <summary>
  67 + /// 使用总数量
  68 + /// </summary>
  69 + public int TotalUsageQuantity { get; set; }
  70 +
  71 + /// <summary>
  72 + /// 使用总金额
  73 + /// </summary>
  74 + public decimal TotalUsageAmount { get; set; }
  75 +
  76 + /// <summary>
  77 + /// 使用次数
  78 + /// </summary>
  79 + public int UsageCount { get; set; }
  80 +
  81 + /// <summary>
  82 + /// 使用产品种类数
  83 + /// </summary>
  84 + public int ProductVarietyCount { get; set; }
  85 + }
  86 +
  87 + /// <summary>
  88 + /// 使用趋势统计输出
  89 + /// </summary>
  90 + public class UsageTrendStatisticsOutput
  91 + {
  92 + /// <summary>
  93 + /// 统计日期
  94 + /// </summary>
  95 + public DateTime StatisticsDate { get; set; }
  96 +
  97 + /// <summary>
  98 + /// 使用总数量
  99 + /// </summary>
  100 + public int TotalUsageQuantity { get; set; }
  101 +
  102 + /// <summary>
  103 + /// 使用总金额
  104 + /// </summary>
  105 + public decimal TotalUsageAmount { get; set; }
  106 +
  107 + /// <summary>
  108 + /// 使用次数
  109 + /// </summary>
  110 + public int UsageCount { get; set; }
  111 +
  112 + /// <summary>
  113 + /// 使用产品种类数
  114 + /// </summary>
  115 + public int ProductVarietyCount { get; set; }
  116 + }
  117 +
  118 + /// <summary>
  119 + /// 产品使用排行榜输出
  120 + /// </summary>
  121 + public class ProductUsageRankingOutput
  122 + {
  123 + /// <summary>
  124 + /// 排名
  125 + /// </summary>
  126 + public int Ranking { get; set; }
  127 +
  128 + /// <summary>
  129 + /// 产品ID
  130 + /// </summary>
  131 + public string ProductId { get; set; }
  132 +
  133 + /// <summary>
  134 + /// 产品名称
  135 + /// </summary>
  136 + public string ProductName { get; set; }
  137 +
  138 + /// <summary>
  139 + /// 产品类别
  140 + /// </summary>
  141 + public string ProductCategory { get; set; }
  142 +
  143 + /// <summary>
  144 + /// 使用总数量
  145 + /// </summary>
  146 + public int TotalUsageQuantity { get; set; }
  147 +
  148 + /// <summary>
  149 + /// 使用总金额
  150 + /// </summary>
  151 + public decimal TotalUsageAmount { get; set; }
  152 +
  153 + /// <summary>
  154 + /// 使用次数
  155 + /// </summary>
  156 + public int UsageCount { get; set; }
  157 +
  158 + /// <summary>
  159 + /// 使用门店数
  160 + /// </summary>
  161 + public int StoreCount { get; set; }
  162 + }
  163 +}
... ...
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqInventoryUsage/LqInventoryUsageUpInput.cs 0 → 100644
  1 +using System;
  2 +using System.ComponentModel.DataAnnotations;
  3 +
  4 +namespace NCC.Extend.Entitys.Dto.LqInventoryUsage
  5 +{
  6 + /// <summary>
  7 + /// 库存使用记录更新输入
  8 + /// </summary>
  9 + public class LqInventoryUsageUpInput : LqInventoryUsageCrInput
  10 + {
  11 + /// <summary>
  12 + /// 使用记录ID
  13 + /// </summary>
  14 + [Required(ErrorMessage = "使用记录ID不能为空")]
  15 + [StringLength(50, ErrorMessage = "使用记录ID长度不能超过50个字符")]
  16 + [Display(Name = "使用记录ID")]
  17 + public string Id { get; set; }
  18 + }
  19 +}
... ...
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdKdjlb/LqKdKdjlbListQueryInput.cs
... ... @@ -48,21 +48,20 @@ namespace NCC.Extend.Entitys.Dto.LqKdKdjlb
48 48 /// 合作机构
49 49 /// </summary>
50 50 public string hgjg { get; set; }
51   -
52 51 /// <summary>
53 52 /// 整单业绩
54 53 /// </summary>
55   - public string zdyj { get; set; }
  54 + public decimal? zdyj { get; set; }
56 55  
57 56 /// <summary>
58 57 /// 实付业绩
59 58 /// </summary>
60   - public string sfyj { get; set; }
  59 + public decimal? sfyj { get; set; }
61 60  
62 61 /// <summary>
63 62 /// 欠款
64 63 /// </summary>
65   - public string qk { get; set; }
  64 + public decimal? qk { get; set; }
66 65  
67 66 /// <summary>
68 67 /// 储扣方式
... ... @@ -135,5 +134,10 @@ namespace NCC.Extend.Entitys.Dto.LqKdKdjlb
135 134 /// </summary>
136 135 public string CreateUser { get; set; }
137 136  
  137 + /// <summary>
  138 + /// 是否有效
  139 + /// </summary>
  140 + public int isEffective { get; set; } = 0;
  141 +
138 142 }
139 143 }
... ...
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdKdjlb/TransferCardInput.cs 0 → 100644
  1 +using System.Collections.Generic;
  2 +using System.ComponentModel.DataAnnotations;
  3 +
  4 +namespace NCC.Extend.Entitys.Dto.LqKdKdjlb
  5 +{
  6 + /// <summary>
  7 + /// 转卡输入参数
  8 + /// </summary>
  9 + public class TransferCardInput
  10 + {
  11 + /// <summary>
  12 + /// 转出会员ID
  13 + /// </summary>
  14 + [Required(ErrorMessage = "转出会员ID不能为空")]
  15 + [StringLength(50, ErrorMessage = "转出会员ID长度不能超过50个字符")]
  16 + [Display(Name = "转出会员ID")]
  17 + public string FromMemberId { get; set; }
  18 +
  19 + /// <summary>
  20 + /// 转入会员ID
  21 + /// </summary>
  22 + [Required(ErrorMessage = "转入会员ID不能为空")]
  23 + [StringLength(50, ErrorMessage = "转入会员ID长度不能超过50个字符")]
  24 + [Display(Name = "转入会员ID")]
  25 + public string ToMemberId { get; set; }
  26 +
  27 + /// <summary>
  28 + /// 转出会员签名
  29 + /// </summary>
  30 + [Required(ErrorMessage = "传出会员签名不能为空")]
  31 + [Display(Name = "传出会员签名")]
  32 + public string SignatureFile { get; set; }
  33 +
  34 + /// <summary>
  35 + /// 转出品项列表
  36 + /// </summary>
  37 + [Required(ErrorMessage = "转出品项列表不能为空")]
  38 + [Display(Name = "转出品项列表")]
  39 + public List<TransferItemInput> TransferItems { get; set; }
  40 +
  41 + /// <summary>
  42 + /// 转卡备注
  43 + /// </summary>
  44 + [StringLength(500, ErrorMessage = "转卡备注长度不能超过500个字符")]
  45 + [Display(Name = "转卡备注")]
  46 + public string Remarks { get; set; }
  47 +
  48 + /// <summary>
  49 + /// 门店ID
  50 + /// </summary>
  51 + [Required(ErrorMessage = "门店ID不能为空")]
  52 + [StringLength(50, ErrorMessage = "门店ID长度不能超过50个字符")]
  53 + [Display(Name = "门店ID")]
  54 + public string StoreId { get; set; }
  55 + }
  56 +
  57 + /// <summary>
  58 + /// 转卡品项输入参数
  59 + /// </summary>
  60 + public class TransferItemInput
  61 + {
  62 + /// <summary>
  63 + /// 开单品项明细ID
  64 + /// </summary>
  65 + [Required(ErrorMessage = "开单品项明细ID不能为空")]
  66 + [StringLength(50, ErrorMessage = "开单品项明细ID长度不能超过50个字符")]
  67 + [Display(Name = "开单品项明细ID")]
  68 + public string BillingItemId { get; set; }
  69 +
  70 + /// <summary>
  71 + /// 转出数量
  72 + /// </summary>
  73 + [Required(ErrorMessage = "转出数量不能为空")]
  74 + [Range(1, int.MaxValue, ErrorMessage = "转出数量必须大于0")]
  75 + [Display(Name = "转出数量")]
  76 + public int TransferQuantity { get; set; }
  77 +
  78 + /// <summary>
  79 + /// 品项名称
  80 + /// </summary>
  81 + [Required(ErrorMessage = "品项名称不能为空")]
  82 + [StringLength(100, ErrorMessage = "品项名称长度不能超过100个字符")]
  83 + [Display(Name = "品项名称")]
  84 + public string ItemName { get; set; }
  85 +
  86 + /// <summary>
  87 + /// 品项价格
  88 + /// </summary>
  89 + [Required(ErrorMessage = "品项价格不能为空")]
  90 + [Range(0, double.MaxValue, ErrorMessage = "品项价格不能为负数")]
  91 + [Display(Name = "品项价格")]
  92 + public decimal ItemPrice { get; set; }
  93 +
  94 + }
  95 +}
... ...
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdKdjlb/TransferCardOutput.cs 0 → 100644
  1 +using System;
  2 +
  3 +namespace NCC.Extend.Entitys.Dto.LqKdKdjlb
  4 +{
  5 + /// <summary>
  6 + /// 转卡输出参数
  7 + /// </summary>
  8 + public class TransferCardOutput
  9 + {
  10 + /// <summary>
  11 + /// 转卡是否成功
  12 + /// </summary>
  13 + public bool Success { get; set; }
  14 +
  15 + /// <summary>
  16 + /// 转卡记录ID(退卡记录ID)
  17 + /// </summary>
  18 + public string TransferId { get; set; }
  19 +
  20 + /// <summary>
  21 + /// 退卡记录ID
  22 + /// </summary>
  23 + public string RefundId { get; set; }
  24 +
  25 + /// <summary>
  26 + /// 开卡记录ID
  27 + /// </summary>
  28 + public string BillingId { get; set; }
  29 +
  30 + /// <summary>
  31 + /// 转卡总金额
  32 + /// </summary>
  33 + public decimal TotalAmount { get; set; }
  34 +
  35 + /// <summary>
  36 + /// 转卡品项数量
  37 + /// </summary>
  38 + public int TotalQuantity { get; set; }
  39 +
  40 + /// <summary>
  41 + /// 转出会员姓名
  42 + /// </summary>
  43 + public string FromMemberName { get; set; }
  44 +
  45 + /// <summary>
  46 + /// 转入会员姓名
  47 + /// </summary>
  48 + public string ToMemberName { get; set; }
  49 +
  50 + /// <summary>
  51 + /// 转卡时间
  52 + /// </summary>
  53 + public DateTime TransferTime { get; set; }
  54 +
  55 + /// <summary>
  56 + /// 消息
  57 + /// </summary>
  58 + public string Message { get; set; }
  59 + }
  60 +}
... ...
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStatistics/LqDepartmentConsumePerformanceStatisticsListOutput.cs
... ... @@ -62,12 +62,23 @@ namespace NCC.Extend.Entitys.Dto.LqStatistics
62 62 /// </summary>
63 63 public decimal HeadCount { get; set; }
64 64  
  65 +
65 66 /// <summary>
66 67 /// 人次(日度去重到店数)
67 68 /// </summary>
68 69 public decimal PersonCount { get; set; }
69 70  
70 71 /// <summary>
  72 + /// 退款业绩
  73 + /// </summary>
  74 + public decimal RefundAmount { get; set; }
  75 +
  76 + /// <summary>
  77 + /// 退款次数
  78 + /// </summary>
  79 + public int RefundCount { get; set; }
  80 +
  81 + /// <summary>
71 82 /// 创建时间
72 83 /// </summary>
73 84 public DateTime CreateTime { get; set; }
... ...
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStatistics/LqStoreTotalPerformanceStatisticsListOutput.cs
... ... @@ -63,6 +63,16 @@ namespace NCC.Extend.Entitys.Dto.LqStatistics
63 63 public int UpgradeOrderCount { get; set; }
64 64  
65 65 /// <summary>
  66 + /// 退款业绩
  67 + /// </summary>
  68 + public decimal RefundAmount { get; set; }
  69 +
  70 + /// <summary>
  71 + /// 退款次数
  72 + /// </summary>
  73 + public int RefundCount { get; set; }
  74 +
  75 + /// <summary>
66 76 /// 创建时间
67 77 /// </summary>
68 78 public DateTime CreateTime { get; set; }
... ...
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStatisticsStoreTotalPerformance/LqStatisticsStoreTotalPerformanceInfoOutput.cs
... ... @@ -63,6 +63,26 @@ namespace NCC.Extend.Entitys.Dto.LqStatisticsStoreTotalPerformance
63 63 public int upgradeOrderCount { get; set; }
64 64  
65 65 /// <summary>
  66 + /// 首单业绩
  67 + /// </summary>
  68 + public decimal firstOrderPerformance { get; set; }
  69 +
  70 + /// <summary>
  71 + /// 升单业绩
  72 + /// </summary>
  73 + public decimal upgradeOrderPerformance { get; set; }
  74 +
  75 + /// <summary>
  76 + /// 退款业绩
  77 + /// </summary>
  78 + public decimal refundAmount { get; set; }
  79 +
  80 + /// <summary>
  81 + /// 退款次数
  82 + /// </summary>
  83 + public int refundCount { get; set; }
  84 +
  85 + /// <summary>
66 86 /// 创建时间
67 87 /// </summary>
68 88 public DateTime? createTime { get; set; }
... ...
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStatisticsStoreTotalPerformance/LqStatisticsStoreTotalPerformanceListOutput.cs
... ... @@ -73,6 +73,16 @@ namespace NCC.Extend.Entitys.Dto.LqStatisticsStoreTotalPerformance
73 73 public decimal upgradeOrderPerformance { get; set; }
74 74  
75 75 /// <summary>
  76 + /// 退款业绩
  77 + /// </summary>
  78 + public decimal refundAmount { get; set; }
  79 +
  80 + /// <summary>
  81 + /// 退款次数
  82 + /// </summary>
  83 + public int refundCount { get; set; }
  84 +
  85 + /// <summary>
76 86 /// 创建时间
77 87 /// </summary>
78 88 public DateTime? createTime { get; set; }
... ...
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStudyClass/LqStudyClassAddStudentsInput.cs 0 → 100644
  1 +using System;
  2 +using System.Collections.Generic;
  3 +using System.ComponentModel.DataAnnotations;
  4 +
  5 +namespace NCC.Extend.Entitys.Dto.LqStudyClass
  6 +{
  7 + /// <summary>
  8 + /// 向学习班级添加学员输入
  9 + /// </summary>
  10 + public class LqStudyClassAddStudentsInput
  11 + {
  12 + /// <summary>
  13 + /// 班级ID
  14 + /// </summary>
  15 + [Required(ErrorMessage = "班级ID不能为空")]
  16 + [StringLength(50, ErrorMessage = "班级ID长度不能超过50个字符")]
  17 + [Display(Name = "班级ID")]
  18 + public string ClassId { get; set; }
  19 +
  20 + /// <summary>
  21 + /// </summary>
  22 + [Required(ErrorMessage = "学员列表不能为空")]
  23 + [Display(Name = "学员列表")]
  24 + public List<LqStudyStudentCreateInput> Students { get; set; } = new List<LqStudyStudentCreateInput>();
  25 + }
  26 +}
... ...
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStudyClass/LqStudyClassCrInput.cs 0 → 100644
  1 +using System;
  2 +using System.ComponentModel.DataAnnotations;
  3 +
  4 +namespace NCC.Extend.Entitys.Dto.LqStudyClass
  5 +{
  6 + /// <summary>
  7 + /// 学习班级创建输入
  8 + /// </summary>
  9 + public class LqStudyClassCrInput
  10 + {
  11 + /// <summary>
  12 + /// 班级名称
  13 + /// </summary>
  14 + [Required(ErrorMessage = "班级名称不能为空")]
  15 + [StringLength(100, ErrorMessage = "班级名称长度不能超过100个字符")]
  16 + [Display(Name = "班级名称")]
  17 + public string ClassName { get; set; }
  18 +
  19 + /// <summary>
  20 + /// 任教老师ID
  21 + /// </summary>
  22 + [Required(ErrorMessage = "任教老师ID不能为空")]
  23 + [StringLength(50, ErrorMessage = "任教老师ID长度不能超过50个字符")]
  24 + [Display(Name = "任教老师ID")]
  25 + public string TeacherId { get; set; }
  26 +
  27 + /// <summary>
  28 + /// 开始时间
  29 + /// </summary>
  30 + [Required(ErrorMessage = "开始时间不能为空")]
  31 + [Display(Name = "开始时间")]
  32 + public DateTime StartTime { get; set; }
  33 +
  34 + /// <summary>
  35 + /// 结束时间
  36 + /// </summary>
  37 + [Required(ErrorMessage = "结束时间不能为空")]
  38 + [Display(Name = "结束时间")]
  39 + public DateTime EndTime { get; set; }
  40 +
  41 + /// <summary>
  42 + /// 备注
  43 + /// </summary>
  44 + [StringLength(500, ErrorMessage = "备注长度不能超过500个字符")]
  45 + [Display(Name = "备注")]
  46 + public string Remark { get; set; }
  47 + }
  48 +}
... ...
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStudyClass/LqStudyClassCreateWithStudentsInput.cs 0 → 100644
  1 +using System;
  2 +using System.Collections.Generic;
  3 +using System.ComponentModel.DataAnnotations;
  4 +
  5 +namespace NCC.Extend.Entitys.Dto.LqStudyClass
  6 +{
  7 + /// <summary>
  8 + /// 创建学习班级并添加学员输入
  9 + /// </summary>
  10 + public class LqStudyClassCreateWithStudentsInput
  11 + {
  12 + /// <summary>
  13 + /// 班级名称
  14 + /// </summary>
  15 + [Required(ErrorMessage = "班级名称不能为空")]
  16 + [StringLength(100, ErrorMessage = "班级名称长度不能超过100个字符")]
  17 + [Display(Name = "班级名称")]
  18 + public string ClassName { get; set; }
  19 +
  20 + /// <summary>
  21 + /// 任教老师ID
  22 + /// </summary>
  23 + [Required(ErrorMessage = "任教老师ID不能为空")]
  24 + [StringLength(50, ErrorMessage = "任教老师ID长度不能超过50个字符")]
  25 + [Display(Name = "任教老师ID")]
  26 + public string TeacherId { get; set; }
  27 +
  28 + /// <summary>
  29 + /// 开始时间
  30 + /// </summary>
  31 + [Required(ErrorMessage = "开始时间不能为空")]
  32 + [Display(Name = "开始时间")]
  33 + public DateTime StartTime { get; set; }
  34 +
  35 + /// <summary>
  36 + /// 结束时间
  37 + /// </summary>
  38 + [Required(ErrorMessage = "结束时间不能为空")]
  39 + [Display(Name = "结束时间")]
  40 + public DateTime EndTime { get; set; }
  41 +
  42 + /// <summary>
  43 + /// 备注
  44 + /// </summary>
  45 + [StringLength(500, ErrorMessage = "备注长度不能超过500个字符")]
  46 + [Display(Name = "备注")]
  47 + public string Remark { get; set; }
  48 +
  49 + /// <summary>
  50 + /// 学员列表
  51 + /// </summary>
  52 + [Display(Name = "学员列表")]
  53 + public List<LqStudyStudentCreateInput> Students { get; set; } = new List<LqStudyStudentCreateInput>();
  54 + }
  55 +
  56 + /// <summary>
  57 + /// 学员创建输入
  58 + /// </summary>
  59 + public class LqStudyStudentCreateInput
  60 + {
  61 + /// <summary>
  62 + /// 员工姓名
  63 + /// </summary>
  64 + [Required(ErrorMessage = "员工姓名不能为空")]
  65 + [StringLength(50, ErrorMessage = "员工姓名长度不能超过50个字符")]
  66 + [Display(Name = "员工姓名")]
  67 + public string EmployeeName { get; set; }
  68 +
  69 + /// <summary>
  70 + /// 员工电话
  71 + /// </summary>
  72 + [Required(ErrorMessage = "员工电话不能为空")]
  73 + [StringLength(20, ErrorMessage = "员工电话长度不能超过20个字符")]
  74 + [Display(Name = "员工电话")]
  75 + public string EmployeePhone { get; set; }
  76 +
  77 + /// <summary>
  78 + /// 员工ID
  79 + /// </summary>
  80 + [Required(ErrorMessage = "员工ID不能为空")]
  81 + [StringLength(50, ErrorMessage = "员工ID长度不能超过50个字符")]
  82 + [Display(Name = "员工ID")]
  83 + public string EmployeeId { get; set; }
  84 +
  85 + /// <summary>
  86 + /// 入院时间
  87 + /// </summary>
  88 + [Required(ErrorMessage = "入院时间不能为空")]
  89 + [Display(Name = "入院时间")]
  90 + public DateTime AdmissionTime { get; set; }
  91 +
  92 + /// <summary>
  93 + /// HR归属
  94 + /// </summary>
  95 + [StringLength(50, ErrorMessage = "HR归属长度不能超过50个字符")]
  96 + [Display(Name = "HR归属")]
  97 + public string HrBelong { get; set; }
  98 + }
  99 +}
... ...
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStudyClass/LqStudyClassInfoOutput.cs 0 → 100644
  1 +using System;
  2 +
  3 +namespace NCC.Extend.Entitys.Dto.LqStudyClass
  4 +{
  5 + /// <summary>
  6 + /// 学习班级详情输出
  7 + /// </summary>
  8 + public class LqStudyClassInfoOutput
  9 + {
  10 + /// <summary>
  11 + /// 班级ID
  12 + /// </summary>
  13 + public string Id { get; set; }
  14 +
  15 + /// <summary>
  16 + /// 班级名称
  17 + /// </summary>
  18 + public string ClassName { 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 TeacherPhone { get; set; }
  34 +
  35 + /// <summary>
  36 + /// 开始时间
  37 + /// </summary>
  38 + public DateTime StartTime { get; set; }
  39 +
  40 + /// <summary>
  41 + /// 结束时间
  42 + /// </summary>
  43 + public DateTime EndTime { get; set; }
  44 +
  45 + /// <summary>
  46 + /// 备注
  47 + /// </summary>
  48 + public string Remark { get; set; }
  49 +
  50 + /// <summary>
  51 + /// 创建人ID
  52 + /// </summary>
  53 + public string CreateUser { get; set; }
  54 +
  55 + /// <summary>
  56 + /// 创建人姓名
  57 + /// </summary>
  58 + public string CreateUserName { get; set; }
  59 +
  60 + /// <summary>
  61 + /// 创建时间
  62 + /// </summary>
  63 + public DateTime CreateTime { get; set; }
  64 +
  65 + /// <summary>
  66 + /// 更新人ID
  67 + /// </summary>
  68 + public string UpdateUser { get; set; }
  69 +
  70 + /// <summary>
  71 + /// 更新人姓名
  72 + /// </summary>
  73 + public string UpdateUserName { get; set; }
  74 +
  75 + /// <summary>
  76 + /// 更新时间
  77 + /// </summary>
  78 + public DateTime? UpdateTime { get; set; }
  79 +
  80 + /// <summary>
  81 + /// 是否有效(1:有效 0:无效)
  82 + /// </summary>
  83 + public int IsEffective { get; set; }
  84 +
  85 + /// <summary>
  86 + /// 学员数量
  87 + /// </summary>
  88 + public int StudentCount { get; set; }
  89 +
  90 + /// <summary>
  91 + /// 学习记录数量
  92 + /// </summary>
  93 + public int RecordCount { get; set; }
  94 + }
  95 +}
... ...
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStudyClass/LqStudyClassListOutput.cs 0 → 100644
  1 +using System;
  2 +using System.ComponentModel.DataAnnotations;
  3 +
  4 +namespace NCC.Extend.Entitys.Dto.LqStudyClass
  5 +{
  6 + /// <summary>
  7 + /// 学习班级列表输出
  8 + /// </summary>
  9 + public class LqStudyClassListOutput
  10 + {
  11 + /// <summary>
  12 + /// 班级ID
  13 + /// </summary>
  14 + [Display(Name = "班级ID")]
  15 + public string id { get; set; }
  16 +
  17 + /// <summary>
  18 + /// 班级名称
  19 + /// </summary>
  20 + [Display(Name = "班级名称")]
  21 + public string className { get; set; }
  22 +
  23 + /// <summary>
  24 + /// 任教老师ID
  25 + /// </summary>
  26 + [Display(Name = "任教老师ID")]
  27 + public string teacherId { get; set; }
  28 +
  29 + /// <summary>
  30 + /// 任教老师姓名
  31 + /// </summary>
  32 + [Display(Name = "任教老师姓名")]
  33 + public string teacherName { get; set; }
  34 +
  35 + /// <summary>
  36 + /// 开始时间
  37 + /// </summary>
  38 + [Display(Name = "开始时间")]
  39 + public DateTime startTime { get; set; }
  40 +
  41 + /// <summary>
  42 + /// 结束时间
  43 + /// </summary>
  44 + [Display(Name = "结束时间")]
  45 + public DateTime endTime { get; set; }
  46 +
  47 + /// <summary>
  48 + /// 备注
  49 + /// </summary>
  50 + [Display(Name = "备注")]
  51 + public string remark { get; set; }
  52 +
  53 + /// <summary>
  54 + /// 学员数量
  55 + /// </summary>
  56 + [Display(Name = "学员数量")]
  57 + public int studentCount { get; set; }
  58 +
  59 + /// <summary>
  60 + /// 创建人ID
  61 + /// </summary>
  62 + [Display(Name = "创建人ID")]
  63 + public string createUser { get; set; }
  64 +
  65 + /// <summary>
  66 + /// 创建人姓名
  67 + /// </summary>
  68 + [Display(Name = "创建人姓名")]
  69 + public string createUserName { get; set; }
  70 +
  71 + /// <summary>
  72 + /// 创建时间
  73 + /// </summary>
  74 + [Display(Name = "创建时间")]
  75 + public DateTime createTime { get; set; }
  76 +
  77 + /// <summary>
  78 + /// 更新人ID
  79 + /// </summary>
  80 + [Display(Name = "更新人ID")]
  81 + public string updateUser { get; set; }
  82 +
  83 + /// <summary>
  84 + /// 更新人姓名
  85 + /// </summary>
  86 + [Display(Name = "更新人姓名")]
  87 + public string updateUserName { get; set; }
  88 +
  89 + /// <summary>
  90 + /// 更新时间
  91 + /// </summary>
  92 + [Display(Name = "更新时间")]
  93 + public DateTime? updateTime { get; set; }
  94 +
  95 + /// <summary>
  96 + /// 是否有效
  97 + /// </summary>
  98 + [Display(Name = "是否有效")]
  99 + public int isEffective { get; set; }
  100 + }
  101 +}
0 102 \ No newline at end of file
... ...
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStudyClass/LqStudyClassListQueryInput.cs 0 → 100644
  1 +using NCC.Common.Filter;
  2 +using System;
  3 +using System.ComponentModel.DataAnnotations;
  4 +
  5 +namespace NCC.Extend.Entitys.Dto.LqStudyClass
  6 +{
  7 + /// <summary>
  8 + /// 学习班级列表查询输入
  9 + /// </summary>
  10 + public class LqStudyClassListQueryInput : PageInputBase
  11 + {
  12 + /// <summary>
  13 + /// 班级名称
  14 + /// </summary>
  15 + [Display(Name = "班级名称", Description = "根据班级名称筛选")]
  16 + public string ClassName { get; set; }
  17 +
  18 + /// <summary>
  19 + /// 任教老师ID
  20 + /// </summary>
  21 + [Display(Name = "任教老师ID", Description = "根据任教老师ID筛选")]
  22 + public string TeacherId { get; set; }
  23 +
  24 + /// <summary>
  25 + /// 开始时间(班级开始时间范围)
  26 + /// </summary>
  27 + [Display(Name = "开始时间", Description = "班级开始时间的开始范围")]
  28 + public DateTime? StartTime { get; set; }
  29 +
  30 + /// <summary>
  31 + /// 结束时间(班级开始时间范围)
  32 + /// </summary>
  33 + [Display(Name = "结束时间", Description = "班级开始时间的结束范围")]
  34 + public DateTime? EndTime { get; set; }
  35 +
  36 + /// <summary>
  37 + /// 是否有效
  38 + /// </summary>
  39 + [Display(Name = "是否有效", Description = "根据是否有效筛选")]
  40 + public int? IsEffective { get; set; }
  41 + }
  42 +}
0 43 \ No newline at end of file
... ...
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStudyClass/LqStudyClassUpInput.cs 0 → 100644
  1 +using System;
  2 +using System.ComponentModel.DataAnnotations;
  3 +
  4 +namespace NCC.Extend.Entitys.Dto.LqStudyClass
  5 +{
  6 + /// <summary>
  7 + /// 学习班级更新输入
  8 + /// </summary>
  9 + public class LqStudyClassUpInput : LqStudyClassCrInput
  10 + {
  11 + /// <summary>
  12 + /// 班级ID
  13 + /// </summary>
  14 + [Required(ErrorMessage = "班级ID不能为空")]
  15 + [StringLength(50, ErrorMessage = "班级ID长度不能超过50个字符")]
  16 + [Display(Name = "班级ID")]
  17 + public string Id { get; set; }
  18 + }
  19 +}
... ...
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStudyClass/LqStudyRecordCreateInput.cs 0 → 100644
  1 +using System;
  2 +using System.ComponentModel.DataAnnotations;
  3 +
  4 +namespace NCC.Extend.Entitys.Dto.LqStudyClass
  5 +{
  6 + /// <summary>
  7 + /// 添加学习记录输入
  8 + /// </summary>
  9 + public class LqStudyRecordCreateInput
  10 + {
  11 + /// <summary>
  12 + /// 员工姓名
  13 + /// </summary>
  14 + [Required(ErrorMessage = "员工姓名不能为空")]
  15 + [StringLength(50, ErrorMessage = "员工姓名长度不能超过50个字符")]
  16 + [Display(Name = "员工姓名")]
  17 + public string EmployeeName { get; set; }
  18 +
  19 + /// <summary>
  20 + /// 员工ID
  21 + /// </summary>
  22 + [Required(ErrorMessage = "员工ID不能为空")]
  23 + [StringLength(50, ErrorMessage = "员工ID长度不能超过50个字符")]
  24 + [Display(Name = "员工ID")]
  25 + public string EmployeeId { get; set; }
  26 +
  27 + /// <summary>
  28 + /// 学习类型
  29 + /// </summary>
  30 + [Required(ErrorMessage = "学习类型不能为空")]
  31 + [StringLength(50, ErrorMessage = "学习类型长度不能超过50个字符")]
  32 + [Display(Name = "学习类型")]
  33 + public string StudyType { get; set; }
  34 +
  35 + /// <summary>
  36 + /// 交通费
  37 + /// </summary>
  38 + [Range(0, double.MaxValue, ErrorMessage = "交通费不能为负数")]
  39 + [Display(Name = "交通费")]
  40 + public decimal? TransportFee { get; set; }
  41 +
  42 + /// <summary>
  43 + /// 学习日期
  44 + /// </summary>
  45 + [Required(ErrorMessage = "学习日期不能为空")]
  46 + [Display(Name = "学习日期")]
  47 + public DateTime StudyDate { get; set; }
  48 +
  49 + /// <summary>
  50 + /// 当日状态
  51 + /// </summary>
  52 + [StringLength(50, ErrorMessage = "当日状态长度不能超过50个字符")]
  53 + [Display(Name = "当日状态")]
  54 + public string DailyStatus { get; set; }
  55 +
  56 + /// <summary>
  57 + /// 备注
  58 + /// </summary>
  59 + [StringLength(500, ErrorMessage = "备注长度不能超过500个字符")]
  60 + [Display(Name = "备注")]
  61 + public string Remark { get; set; }
  62 +
  63 + /// <summary>
  64 + /// 是否下店协助(1:是 0:否)
  65 + /// </summary>
  66 + [Display(Name = "是否下店协助")]
  67 + public int IsStoreAssist { get; set; } = 0;
  68 +
  69 + /// <summary>
  70 + /// 下店门店ID
  71 + /// </summary>
  72 + [StringLength(50, ErrorMessage = "下店门店ID长度不能超过50个字符")]
  73 + [Display(Name = "下店门店ID")]
  74 + public string StoreId { get; set; }
  75 +
  76 + /// <summary>
  77 + /// 下店门店名称
  78 + /// </summary>
  79 + [StringLength(100, ErrorMessage = "下店门店名称长度不能超过100个字符")]
  80 + [Display(Name = "下店门店名称")]
  81 + public string StoreName { get; set; }
  82 + }
  83 +}
... ...
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStudyClass/LqStudyRecordListOutput.cs 0 → 100644
  1 +using System;
  2 +using System.ComponentModel.DataAnnotations;
  3 +
  4 +namespace NCC.Extend.Entitys.Dto.LqStudyClass
  5 +{
  6 + /// <summary>
  7 + /// 学习记录列表输出
  8 + /// </summary>
  9 + public class LqStudyRecordListOutput
  10 + {
  11 + /// <summary>
  12 + /// 学习记录ID
  13 + /// </summary>
  14 + [Display(Name = "学习记录ID")]
  15 + public string id { get; set; }
  16 +
  17 + /// <summary>
  18 + /// 员工姓名
  19 + /// </summary>
  20 + [Display(Name = "员工姓名")]
  21 + public string employeeName { get; set; }
  22 +
  23 + /// <summary>
  24 + /// 员工ID
  25 + /// </summary>
  26 + [Display(Name = "员工ID")]
  27 + public string employeeId { get; set; }
  28 +
  29 + /// <summary>
  30 + /// 学习类型
  31 + /// </summary>
  32 + [Display(Name = "学习类型")]
  33 + public string studyType { get; set; }
  34 +
  35 + /// <summary>
  36 + /// 交通费
  37 + /// </summary>
  38 + [Display(Name = "交通费")]
  39 + public decimal? transportFee { get; set; }
  40 +
  41 + /// <summary>
  42 + /// 学习日期
  43 + /// </summary>
  44 + [Display(Name = "学习日期")]
  45 + public DateTime studyDate { get; set; }
  46 +
  47 + /// <summary>
  48 + /// 当日状态
  49 + /// </summary>
  50 + [Display(Name = "当日状态")]
  51 + public string dailyStatus { get; set; }
  52 +
  53 + /// <summary>
  54 + /// 备注
  55 + /// </summary>
  56 + [Display(Name = "备注")]
  57 + public string remark { get; set; }
  58 +
  59 + /// <summary>
  60 + /// 是否下店协助
  61 + /// </summary>
  62 + [Display(Name = "是否下店协助")]
  63 + public int isStoreAssist { get; set; }
  64 +
  65 + /// <summary>
  66 + /// 下店门店ID
  67 + /// </summary>
  68 + [Display(Name = "下店门店ID")]
  69 + public string storeId { get; set; }
  70 +
  71 + /// <summary>
  72 + /// 下店门店名称
  73 + /// </summary>
  74 + [Display(Name = "下店门店名称")]
  75 + public string storeName { get; set; }
  76 +
  77 + /// <summary>
  78 + /// 创建人ID
  79 + /// </summary>
  80 + [Display(Name = "创建人ID")]
  81 + public string createUser { get; set; }
  82 +
  83 + /// <summary>
  84 + /// 创建人姓名
  85 + /// </summary>
  86 + [Display(Name = "创建人姓名")]
  87 + public string createUserName { get; set; }
  88 +
  89 + /// <summary>
  90 + /// 创建时间
  91 + /// </summary>
  92 + [Display(Name = "创建时间")]
  93 + public DateTime createTime { get; set; }
  94 +
  95 + /// <summary>
  96 + /// 更新人ID
  97 + /// </summary>
  98 + [Display(Name = "更新人ID")]
  99 + public string updateUser { get; set; }
  100 +
  101 + /// <summary>
  102 + /// 更新人姓名
  103 + /// </summary>
  104 + [Display(Name = "更新人姓名")]
  105 + public string updateUserName { get; set; }
  106 +
  107 + /// <summary>
  108 + /// 更新时间
  109 + /// </summary>
  110 + [Display(Name = "更新时间")]
  111 + public DateTime? updateTime { get; set; }
  112 +
  113 + /// <summary>
  114 + /// 是否有效
  115 + /// </summary>
  116 + [Display(Name = "是否有效")]
  117 + public int isEffective { get; set; }
  118 + }
  119 +}
... ...
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStudyClass/LqStudyRecordListQueryInput.cs 0 → 100644
  1 +using NCC.Common.Filter;
  2 +using System;
  3 +using System.ComponentModel.DataAnnotations;
  4 +
  5 +namespace NCC.Extend.Entitys.Dto.LqStudyClass
  6 +{
  7 + /// <summary>
  8 + /// 学习记录列表查询输入
  9 + /// </summary>
  10 + public class LqStudyRecordListQueryInput : PageInputBase
  11 + {
  12 + /// <summary>
  13 + /// 员工姓名
  14 + /// </summary>
  15 + [Display(Name = "员工姓名", Description = "根据员工姓名筛选")]
  16 + public string EmployeeName { get; set; }
  17 +
  18 + /// <summary>
  19 + /// 员工ID
  20 + /// </summary>
  21 + [Display(Name = "员工ID", Description = "根据员工ID筛选")]
  22 + public string EmployeeId { get; set; }
  23 +
  24 + /// <summary>
  25 + /// 学习类型
  26 + /// </summary>
  27 + [Display(Name = "学习类型", Description = "根据学习类型筛选")]
  28 + public string StudyType { get; set; }
  29 +
  30 + /// <summary>
  31 + /// 学习日期开始
  32 + /// </summary>
  33 + [Display(Name = "学习日期开始", Description = "学习日期的开始范围")]
  34 + public DateTime? StudyDateStart { get; set; }
  35 +
  36 + /// <summary>
  37 + /// 学习日期结束
  38 + /// </summary>
  39 + [Display(Name = "学习日期结束", Description = "学习日期的结束范围")]
  40 + public DateTime? StudyDateEnd { get; set; }
  41 +
  42 + /// <summary>
  43 + /// 当日状态
  44 + /// </summary>
  45 + [Display(Name = "当日状态", Description = "根据当日状态筛选")]
  46 + public string DailyStatus { get; set; }
  47 +
  48 + /// <summary>
  49 + /// 是否下店协助
  50 + /// </summary>
  51 + [Display(Name = "是否下店协助", Description = "根据是否下店协助筛选")]
  52 + public int? IsStoreAssist { get; set; }
  53 +
  54 + /// <summary>
  55 + /// 门店ID
  56 + /// </summary>
  57 + [Display(Name = "门店ID", Description = "根据门店ID筛选")]
  58 + public string StoreId { get; set; }
  59 +
  60 + /// <summary>
  61 + /// 是否有效
  62 + /// </summary>
  63 + [Display(Name = "是否有效", Description = "根据是否有效筛选")]
  64 + public int? IsEffective { get; set; }
  65 + }
  66 +}
... ...
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStudyClass/LqStudyStudentListOutput.cs 0 → 100644
  1 +using System;
  2 +using System.ComponentModel.DataAnnotations;
  3 +
  4 +namespace NCC.Extend.Entitys.Dto.LqStudyClass
  5 +{
  6 + /// <summary>
  7 + /// 学习学员列表输出
  8 + /// </summary>
  9 + public class LqStudyStudentListOutput
  10 + {
  11 + /// <summary>
  12 + /// 学员ID
  13 + /// </summary>
  14 + [Display(Name = "学员ID")]
  15 + public string id { get; set; }
  16 +
  17 + /// <summary>
  18 + /// 员工姓名
  19 + /// </summary>
  20 + [Display(Name = "员工姓名")]
  21 + public string employeeName { get; set; }
  22 +
  23 + /// <summary>
  24 + /// 员工电话
  25 + /// </summary>
  26 + [Display(Name = "员工电话")]
  27 + public string employeePhone { get; set; }
  28 +
  29 + /// <summary>
  30 + /// 员工ID
  31 + /// </summary>
  32 + [Display(Name = "员工ID")]
  33 + public string employeeId { get; set; }
  34 +
  35 + /// <summary>
  36 + /// 入院时间
  37 + /// </summary>
  38 + [Display(Name = "入院时间")]
  39 + public DateTime admissionTime { get; set; }
  40 +
  41 + /// <summary>
  42 + /// 班级ID
  43 + /// </summary>
  44 + [Display(Name = "班级ID")]
  45 + public string classId { get; set; }
  46 +
  47 + /// <summary>
  48 + /// 所属班级
  49 + /// </summary>
  50 + [Display(Name = "所属班级")]
  51 + public string className { get; set; }
  52 +
  53 + /// <summary>
  54 + /// HR归属
  55 + /// </summary>
  56 + [Display(Name = "HR归属")]
  57 + public string hrBelong { get; set; }
  58 +
  59 + /// <summary>
  60 + /// 创建人ID
  61 + /// </summary>
  62 + [Display(Name = "创建人ID")]
  63 + public string createUser { get; set; }
  64 +
  65 + /// <summary>
  66 + /// 创建人姓名
  67 + /// </summary>
  68 + [Display(Name = "创建人姓名")]
  69 + public string createUserName { get; set; }
  70 +
  71 + /// <summary>
  72 + /// 创建时间
  73 + /// </summary>
  74 + [Display(Name = "创建时间")]
  75 + public DateTime createTime { get; set; }
  76 +
  77 + /// <summary>
  78 + /// 更新人ID
  79 + /// </summary>
  80 + [Display(Name = "更新人ID")]
  81 + public string updateUser { get; set; }
  82 +
  83 + /// <summary>
  84 + /// 更新人姓名
  85 + /// </summary>
  86 + [Display(Name = "更新人姓名")]
  87 + public string updateUserName { get; set; }
  88 +
  89 + /// <summary>
  90 + /// 更新时间
  91 + /// </summary>
  92 + [Display(Name = "更新时间")]
  93 + public DateTime? updateTime { get; set; }
  94 +
  95 + /// <summary>
  96 + /// 是否有效
  97 + /// </summary>
  98 + [Display(Name = "是否有效")]
  99 + public int isEffective { get; set; }
  100 + }
  101 +}
... ...
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStudyClass/LqStudyStudentListQueryInput.cs 0 → 100644
  1 +using NCC.Common.Filter;
  2 +using System;
  3 +using System.ComponentModel.DataAnnotations;
  4 +
  5 +namespace NCC.Extend.Entitys.Dto.LqStudyClass
  6 +{
  7 + /// <summary>
  8 + /// 学习学员列表查询输入
  9 + /// </summary>
  10 + public class LqStudyStudentListQueryInput : PageInputBase
  11 + {
  12 + /// <summary>
  13 + /// 班级ID
  14 + /// </summary>
  15 + [Required(ErrorMessage = "班级ID不能为空")]
  16 + [Display(Name = "班级ID", Description = "根据班级ID筛选学员")]
  17 + public string ClassId { get; set; }
  18 +
  19 + /// <summary>
  20 + /// 员工姓名
  21 + /// </summary>
  22 + [Display(Name = "员工姓名", Description = "根据员工姓名筛选")]
  23 + public string EmployeeName { get; set; }
  24 +
  25 + /// <summary>
  26 + /// 员工电话
  27 + /// </summary>
  28 + [Display(Name = "员工电话", Description = "根据员工电话筛选")]
  29 + public string EmployeePhone { get; set; }
  30 +
  31 + /// <summary>
  32 + /// 员工ID
  33 + /// </summary>
  34 + [Display(Name = "员工ID", Description = "根据员工ID筛选")]
  35 + public string EmployeeId { get; set; }
  36 +
  37 + /// <summary>
  38 + /// HR归属
  39 + /// </summary>
  40 + [Display(Name = "HR归属", Description = "根据HR归属筛选")]
  41 + public string HrBelong { get; set; }
  42 +
  43 + /// <summary>
  44 + /// 是否有效
  45 + /// </summary>
  46 + [Display(Name = "是否有效", Description = "根据是否有效筛选")]
  47 + public int? IsEffective { get; set; }
  48 + }
  49 +}
... ...
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStudyRecord/LqStudyRecordCrInput.cs 0 → 100644
  1 +using System;
  2 +using System.ComponentModel.DataAnnotations;
  3 +
  4 +namespace NCC.Extend.Entitys.Dto.LqStudyRecord
  5 +{
  6 + /// <summary>
  7 + /// 学习记录创建输入
  8 + /// </summary>
  9 + public class LqStudyRecordCrInput
  10 + {
  11 + /// <summary>
  12 + /// 员工姓名
  13 + /// </summary>
  14 + [Required(ErrorMessage = "员工姓名不能为空")]
  15 + [StringLength(50, ErrorMessage = "员工姓名长度不能超过50个字符")]
  16 + [Display(Name = "员工姓名")]
  17 + public string EmployeeName { get; set; }
  18 +
  19 + /// <summary>
  20 + /// 员工ID
  21 + /// </summary>
  22 + [Required(ErrorMessage = "员工ID不能为空")]
  23 + [StringLength(50, ErrorMessage = "员工ID长度不能超过50个字符")]
  24 + [Display(Name = "员工ID")]
  25 + public string EmployeeId { get; set; }
  26 +
  27 + /// <summary>
  28 + /// 学习类型
  29 + /// </summary>
  30 + [Required(ErrorMessage = "学习类型不能为空")]
  31 + [StringLength(50, ErrorMessage = "学习类型长度不能超过50个字符")]
  32 + [Display(Name = "学习类型")]
  33 + public string StudyType { get; set; }
  34 +
  35 + /// <summary>
  36 + /// 交通费
  37 + /// </summary>
  38 + [Range(0, double.MaxValue, ErrorMessage = "交通费不能小于0")]
  39 + [Display(Name = "交通费")]
  40 + public decimal? TransportFee { get; set; }
  41 +
  42 + /// <summary>
  43 + /// 学习日期
  44 + /// </summary>
  45 + [Required(ErrorMessage = "学习日期不能为空")]
  46 + [Display(Name = "学习日期")]
  47 + public DateTime StudyDate { get; set; }
  48 +
  49 + /// <summary>
  50 + /// 当日状态
  51 + /// </summary>
  52 + [Required(ErrorMessage = "当日状态不能为空")]
  53 + [StringLength(50, ErrorMessage = "当日状态长度不能超过50个字符")]
  54 + [Display(Name = "当日状态")]
  55 + public string DailyStatus { get; set; }
  56 +
  57 + /// <summary>
  58 + /// 备注
  59 + /// </summary>
  60 + [StringLength(1000, ErrorMessage = "备注长度不能超过1000个字符")]
  61 + [Display(Name = "备注")]
  62 + public string Remark { get; set; }
  63 +
  64 + /// <summary>
  65 + /// 是否下店协助(1:是 0:否)
  66 + /// </summary>
  67 + [Display(Name = "是否下店协助")]
  68 + public int IsStoreAssist { get; set; } = 0;
  69 +
  70 + /// <summary>
  71 + /// 下店门店ID
  72 + /// </summary>
  73 + [StringLength(50, ErrorMessage = "下店门店ID长度不能超过50个字符")]
  74 + [Display(Name = "下店门店ID")]
  75 + public string StoreId { get; set; }
  76 +
  77 + /// <summary>
  78 + /// 下店门店名称
  79 + /// </summary>
  80 + [StringLength(100, ErrorMessage = "下店门店名称长度不能超过100个字符")]
  81 + [Display(Name = "下店门店名称")]
  82 + public string StoreName { get; set; }
  83 + }
  84 +}
... ...
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStudyRecord/LqStudyRecordInfoOutput.cs 0 → 100644
  1 +using System;
  2 +
  3 +namespace NCC.Extend.Entitys.Dto.LqStudyRecord
  4 +{
  5 + /// <summary>
  6 + /// 学习记录详情输出
  7 + /// </summary>
  8 + public class LqStudyRecordInfoOutput
  9 + {
  10 + /// <summary>
  11 + /// 学习记录ID
  12 + /// </summary>
  13 + public string Id { get; set; }
  14 +
  15 + /// <summary>
  16 + /// 员工姓名
  17 + /// </summary>
  18 + public string EmployeeName { get; set; }
  19 +
  20 + /// <summary>
  21 + /// 员工ID
  22 + /// </summary>
  23 + public string EmployeeId { get; set; }
  24 +
  25 + /// <summary>
  26 + /// 学习类型
  27 + /// </summary>
  28 + public string StudyType { get; set; }
  29 +
  30 + /// <summary>
  31 + /// 交通费
  32 + /// </summary>
  33 + public decimal? TransportFee { get; set; }
  34 +
  35 + /// <summary>
  36 + /// 学习日期
  37 + /// </summary>
  38 + public DateTime StudyDate { get; set; }
  39 +
  40 + /// <summary>
  41 + /// 当日状态
  42 + /// </summary>
  43 + public string DailyStatus { get; set; }
  44 +
  45 + /// <summary>
  46 + /// 备注
  47 + /// </summary>
  48 + public string Remark { get; set; }
  49 +
  50 + /// <summary>
  51 + /// 是否下店协助(1:是 0:否)
  52 + /// </summary>
  53 + public int IsStoreAssist { get; set; }
  54 +
  55 + /// <summary>
  56 + /// 下店门店ID
  57 + /// </summary>
  58 + public string StoreId { get; set; }
  59 +
  60 + /// <summary>
  61 + /// 下店门店名称
  62 + /// </summary>
  63 + public string StoreName { get; set; }
  64 +
  65 + /// <summary>
  66 + /// 创建人ID
  67 + /// </summary>
  68 + public string CreateUser { get; set; }
  69 +
  70 + /// <summary>
  71 + /// 创建人姓名
  72 + /// </summary>
  73 + public string CreateUserName { get; set; }
  74 +
  75 + /// <summary>
  76 + /// 创建时间
  77 + /// </summary>
  78 + public DateTime CreateTime { get; set; }
  79 +
  80 + /// <summary>
  81 + /// 更新人ID
  82 + /// </summary>
  83 + public string UpdateUser { get; set; }
  84 +
  85 + /// <summary>
  86 + /// 更新人姓名
  87 + /// </summary>
  88 + public string UpdateUserName { get; set; }
  89 +
  90 + /// <summary>
  91 + /// 更新时间
  92 + /// </summary>
  93 + public DateTime? UpdateTime { get; set; }
  94 +
  95 + /// <summary>
  96 + /// 是否有效(1:有效 0:无效)
  97 + /// </summary>
  98 + public int IsEffective { get; set; }
  99 + }
  100 +}
... ...
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStudyRecord/LqStudyRecordListOutput.cs 0 → 100644
  1 +using System;
  2 +
  3 +namespace NCC.Extend.Entitys.Dto.LqStudyRecord
  4 +{
  5 + /// <summary>
  6 + /// 学习记录列表输出
  7 + /// </summary>
  8 + public class LqStudyRecordListOutput
  9 + {
  10 + /// <summary>
  11 + /// 学习记录ID
  12 + /// </summary>
  13 + public string Id { get; set; }
  14 +
  15 + /// <summary>
  16 + /// 员工姓名
  17 + /// </summary>
  18 + public string EmployeeName { get; set; }
  19 +
  20 + /// <summary>
  21 + /// 员工ID
  22 + /// </summary>
  23 + public string EmployeeId { get; set; }
  24 +
  25 + /// <summary>
  26 + /// 学习类型
  27 + /// </summary>
  28 + public string StudyType { get; set; }
  29 +
  30 + /// <summary>
  31 + /// 交通费
  32 + /// </summary>
  33 + public decimal? TransportFee { get; set; }
  34 +
  35 + /// <summary>
  36 + /// 学习日期
  37 + /// </summary>
  38 + public DateTime StudyDate { get; set; }
  39 +
  40 + /// <summary>
  41 + /// 当日状态
  42 + /// </summary>
  43 + public string DailyStatus { get; set; }
  44 +
  45 + /// <summary>
  46 + /// 备注
  47 + /// </summary>
  48 + public string Remark { get; set; }
  49 +
  50 + /// <summary>
  51 + /// 是否下店协助(1:是 0:否)
  52 + /// </summary>
  53 + public int IsStoreAssist { get; set; }
  54 +
  55 + /// <summary>
  56 + /// 下店门店ID
  57 + /// </summary>
  58 + public string StoreId { get; set; }
  59 +
  60 + /// <summary>
  61 + /// 下店门店名称
  62 + /// </summary>
  63 + public string StoreName { get; set; }
  64 +
  65 + /// <summary>
  66 + /// 创建人ID
  67 + /// </summary>
  68 + public string CreateUser { get; set; }
  69 +
  70 + /// <summary>
  71 + /// 创建人姓名
  72 + /// </summary>
  73 + public string CreateUserName { get; set; }
  74 +
  75 + /// <summary>
  76 + /// 创建时间
  77 + /// </summary>
  78 + public DateTime CreateTime { get; set; }
  79 +
  80 + /// <summary>
  81 + /// 更新人ID
  82 + /// </summary>
  83 + public string UpdateUser { get; set; }
  84 +
  85 + /// <summary>
  86 + /// 更新人姓名
  87 + /// </summary>
  88 + public string UpdateUserName { get; set; }
  89 +
  90 + /// <summary>
  91 + /// 更新时间
  92 + /// </summary>
  93 + public DateTime? UpdateTime { get; set; }
  94 +
  95 + /// <summary>
  96 + /// 是否有效(1:有效 0:无效)
  97 + /// </summary>
  98 + public int IsEffective { get; set; }
  99 + }
  100 +}
... ...
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStudyRecord/LqStudyRecordListQueryInput.cs 0 → 100644
  1 +using NCC.Common.Filter;
  2 +
  3 +namespace NCC.Extend.Entitys.Dto.LqStudyRecord
  4 +{
  5 + /// <summary>
  6 + /// 学习记录列表查询输入
  7 + /// </summary>
  8 + public class LqStudyRecordListQueryInput : PageInputBase
  9 + {
  10 + /// <summary>
  11 + /// 员工姓名
  12 + /// </summary>
  13 + public string EmployeeName { get; set; }
  14 +
  15 + /// <summary>
  16 + /// 员工ID
  17 + /// </summary>
  18 + public string EmployeeId { get; set; }
  19 +
  20 + /// <summary>
  21 + /// 学习类型
  22 + /// </summary>
  23 + public string StudyType { get; set; }
  24 +
  25 + /// <summary>
  26 + /// 学习开始日期
  27 + /// </summary>
  28 + public System.DateTime? StudyStartDate { get; set; }
  29 +
  30 + /// <summary>
  31 + /// 学习结束日期
  32 + /// </summary>
  33 + public System.DateTime? StudyEndDate { get; set; }
  34 +
  35 + /// <summary>
  36 + /// 当日状态
  37 + /// </summary>
  38 + public string DailyStatus { get; set; }
  39 +
  40 + /// <summary>
  41 + /// 是否下店协助
  42 + /// </summary>
  43 + public int? IsStoreAssist { get; set; }
  44 +
  45 + /// <summary>
  46 + /// 下店门店ID
  47 + /// </summary>
  48 + public string StoreId { get; set; }
  49 +
  50 + /// <summary>
  51 + /// 是否有效
  52 + /// </summary>
  53 + public int? IsEffective { get; set; }
  54 + }
  55 +}
... ...
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStudyRecord/LqStudyRecordUpInput.cs 0 → 100644
  1 +using System;
  2 +using System.ComponentModel.DataAnnotations;
  3 +
  4 +namespace NCC.Extend.Entitys.Dto.LqStudyRecord
  5 +{
  6 + /// <summary>
  7 + /// 学习记录更新输入
  8 + /// </summary>
  9 + public class LqStudyRecordUpInput : LqStudyRecordCrInput
  10 + {
  11 + /// <summary>
  12 + /// 学习记录ID
  13 + /// </summary>
  14 + [Required(ErrorMessage = "学习记录ID不能为空")]
  15 + [StringLength(50, ErrorMessage = "学习记录ID长度不能超过50个字符")]
  16 + [Display(Name = "学习记录ID")]
  17 + public string Id { get; set; }
  18 + }
  19 +}
... ...
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStudyStudent/LqStudyStudentCrInput.cs 0 → 100644
  1 +using System;
  2 +using System.ComponentModel.DataAnnotations;
  3 +
  4 +namespace NCC.Extend.Entitys.Dto.LqStudyStudent
  5 +{
  6 + /// <summary>
  7 + /// 学习学员创建输入
  8 + /// </summary>
  9 + public class LqStudyStudentCrInput
  10 + {
  11 + /// <summary>
  12 + /// 员工姓名
  13 + /// </summary>
  14 + [Required(ErrorMessage = "员工姓名不能为空")]
  15 + [StringLength(50, ErrorMessage = "员工姓名长度不能超过50个字符")]
  16 + [Display(Name = "员工姓名")]
  17 + public string EmployeeName { get; set; }
  18 +
  19 + /// <summary>
  20 + /// 员工电话
  21 + /// </summary>
  22 + [Required(ErrorMessage = "员工电话不能为空")]
  23 + [StringLength(20, ErrorMessage = "员工电话长度不能超过20个字符")]
  24 + [Display(Name = "员工电话")]
  25 + public string EmployeePhone { get; set; }
  26 +
  27 + /// <summary>
  28 + /// 员工ID
  29 + /// </summary>
  30 + [Required(ErrorMessage = "员工ID不能为空")]
  31 + [StringLength(50, ErrorMessage = "员工ID长度不能超过50个字符")]
  32 + [Display(Name = "员工ID")]
  33 + public string EmployeeId { get; set; }
  34 +
  35 + /// <summary>
  36 + /// 入院时间
  37 + /// </summary>
  38 + [Required(ErrorMessage = "入院时间不能为空")]
  39 + [Display(Name = "入院时间")]
  40 + public DateTime AdmissionTime { get; set; }
  41 +
  42 + /// <summary>
  43 + /// 班级ID
  44 + /// </summary>
  45 + [Required(ErrorMessage = "班级ID不能为空")]
  46 + [StringLength(50, ErrorMessage = "班级ID长度不能超过50个字符")]
  47 + [Display(Name = "班级ID")]
  48 + public string ClassId { get; set; }
  49 +
  50 + /// <summary>
  51 + /// 所属班级
  52 + /// </summary>
  53 + [Required(ErrorMessage = "所属班级不能为空")]
  54 + [StringLength(100, ErrorMessage = "所属班级长度不能超过100个字符")]
  55 + [Display(Name = "所属班级")]
  56 + public string ClassName { get; set; }
  57 +
  58 + /// <summary>
  59 + /// HR归属
  60 + /// </summary>
  61 + [StringLength(50, ErrorMessage = "HR归属长度不能超过50个字符")]
  62 + [Display(Name = "HR归属")]
  63 + public string HrBelong { get; set; }
  64 + }
  65 +}
... ...
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStudyStudent/LqStudyStudentInfoOutput.cs 0 → 100644
  1 +using System;
  2 +
  3 +namespace NCC.Extend.Entitys.Dto.LqStudyStudent
  4 +{
  5 + /// <summary>
  6 + /// 学习学员详情输出
  7 + /// </summary>
  8 + public class LqStudyStudentInfoOutput
  9 + {
  10 + /// <summary>
  11 + /// 学员ID
  12 + /// </summary>
  13 + public string Id { get; set; }
  14 +
  15 + /// <summary>
  16 + /// 员工姓名
  17 + /// </summary>
  18 + public string EmployeeName { get; set; }
  19 +
  20 + /// <summary>
  21 + /// 员工电话
  22 + /// </summary>
  23 + public string EmployeePhone { get; set; }
  24 +
  25 + /// <summary>
  26 + /// 员工ID
  27 + /// </summary>
  28 + public string EmployeeId { get; set; }
  29 +
  30 + /// <summary>
  31 + /// 入院时间
  32 + /// </summary>
  33 + public DateTime AdmissionTime { get; set; }
  34 +
  35 + /// <summary>
  36 + /// 班级ID
  37 + /// </summary>
  38 + public string ClassId { get; set; }
  39 +
  40 + /// <summary>
  41 + /// 所属班级
  42 + /// </summary>
  43 + public string ClassName { get; set; }
  44 +
  45 + /// <summary>
  46 + /// HR归属
  47 + /// </summary>
  48 + public string HrBelong { get; set; }
  49 +
  50 + /// <summary>
  51 + /// 创建人ID
  52 + /// </summary>
  53 + public string CreateUser { get; set; }
  54 +
  55 + /// <summary>
  56 + /// 创建人姓名
  57 + /// </summary>
  58 + public string CreateUserName { get; set; }
  59 +
  60 + /// <summary>
  61 + /// 创建时间
  62 + /// </summary>
  63 + public DateTime CreateTime { get; set; }
  64 +
  65 + /// <summary>
  66 + /// 更新人ID
  67 + /// </summary>
  68 + public string UpdateUser { get; set; }
  69 +
  70 + /// <summary>
  71 + /// 更新人姓名
  72 + /// </summary>
  73 + public string UpdateUserName { get; set; }
  74 +
  75 + /// <summary>
  76 + /// 更新时间
  77 + /// </summary>
  78 + public DateTime? UpdateTime { get; set; }
  79 +
  80 + /// <summary>
  81 + /// 是否有效(1:有效 0:无效)
  82 + /// </summary>
  83 + public int IsEffective { get; set; }
  84 +
  85 + /// <summary>
  86 + /// 学习记录数量
  87 + /// </summary>
  88 + public int RecordCount { get; set; }
  89 +
  90 + /// <summary>
  91 + /// 总交通费
  92 + /// </summary>
  93 + public decimal TotalTransportFee { get; set; }
  94 +
  95 + /// <summary>
  96 + /// 下店协助次数
  97 + /// </summary>
  98 + public int StoreAssistCount { get; set; }
  99 + }
  100 +}
... ...
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStudyStudent/LqStudyStudentListOutput.cs 0 → 100644
  1 +using System;
  2 +
  3 +namespace NCC.Extend.Entitys.Dto.LqStudyStudent
  4 +{
  5 + /// <summary>
  6 + /// 学习学员列表输出
  7 + /// </summary>
  8 + public class LqStudyStudentListOutput
  9 + {
  10 + /// <summary>
  11 + /// 学员ID
  12 + /// </summary>
  13 + public string Id { get; set; }
  14 +
  15 + /// <summary>
  16 + /// 员工姓名
  17 + /// </summary>
  18 + public string EmployeeName { get; set; }
  19 +
  20 + /// <summary>
  21 + /// 员工电话
  22 + /// </summary>
  23 + public string EmployeePhone { get; set; }
  24 +
  25 + /// <summary>
  26 + /// 员工ID
  27 + /// </summary>
  28 + public string EmployeeId { get; set; }
  29 +
  30 + /// <summary>
  31 + /// 入院时间
  32 + /// </summary>
  33 + public DateTime AdmissionTime { get; set; }
  34 +
  35 + /// <summary>
  36 + /// 班级ID
  37 + /// </summary>
  38 + public string ClassId { get; set; }
  39 +
  40 + /// <summary>
  41 + /// 所属班级
  42 + /// </summary>
  43 + public string ClassName { get; set; }
  44 +
  45 + /// <summary>
  46 + /// HR归属
  47 + /// </summary>
  48 + public string HrBelong { get; set; }
  49 +
  50 + /// <summary>
  51 + /// 创建人ID
  52 + /// </summary>
  53 + public string CreateUser { get; set; }
  54 +
  55 + /// <summary>
  56 + /// 创建人姓名
  57 + /// </summary>
  58 + public string CreateUserName { get; set; }
  59 +
  60 + /// <summary>
  61 + /// 创建时间
  62 + /// </summary>
  63 + public DateTime CreateTime { get; set; }
  64 +
  65 + /// <summary>
  66 + /// 更新人ID
  67 + /// </summary>
  68 + public string UpdateUser { get; set; }
  69 +
  70 + /// <summary>
  71 + /// 更新人姓名
  72 + /// </summary>
  73 + public string UpdateUserName { get; set; }
  74 +
  75 + /// <summary>
  76 + /// 更新时间
  77 + /// </summary>
  78 + public DateTime? UpdateTime { get; set; }
  79 +
  80 + /// <summary>
  81 + /// 是否有效(1:有效 0:无效)
  82 + /// </summary>
  83 + public int IsEffective { get; set; }
  84 +
  85 + /// <summary>
  86 + /// 学习记录数量
  87 + /// </summary>
  88 + public int RecordCount { get; set; }
  89 + }
  90 +}
... ...
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStudyStudent/LqStudyStudentListQueryInput.cs 0 → 100644
  1 +using NCC.Common.Filter;
  2 +
  3 +namespace NCC.Extend.Entitys.Dto.LqStudyStudent
  4 +{
  5 + /// <summary>
  6 + /// 学习学员列表查询输入
  7 + /// </summary>
  8 + public class LqStudyStudentListQueryInput : PageInputBase
  9 + {
  10 + /// <summary>
  11 + /// 员工姓名
  12 + /// </summary>
  13 + public string EmployeeName { get; set; }
  14 +
  15 + /// <summary>
  16 + /// 员工电话
  17 + /// </summary>
  18 + public string EmployeePhone { get; set; }
  19 +
  20 + /// <summary>
  21 + /// 员工ID
  22 + /// </summary>
  23 + public string EmployeeId { get; set; }
  24 +
  25 + /// <summary>
  26 + /// 班级ID
  27 + /// </summary>
  28 + public string ClassId { get; set; }
  29 +
  30 + /// <summary>
  31 + /// 所属班级
  32 + /// </summary>
  33 + public string ClassName { get; set; }
  34 +
  35 + /// <summary>
  36 + /// HR归属
  37 + /// </summary>
  38 + public string HrBelong { get; set; }
  39 +
  40 + /// <summary>
  41 + /// 入院开始时间
  42 + /// </summary>
  43 + public System.DateTime? AdmissionStartTime { get; set; }
  44 +
  45 + /// <summary>
  46 + /// 入院结束时间
  47 + /// </summary>
  48 + public System.DateTime? AdmissionEndTime { get; set; }
  49 +
  50 + /// <summary>
  51 + /// 是否有效
  52 + /// </summary>
  53 + public int? IsEffective { get; set; }
  54 + }
  55 +}
... ...
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStudyStudent/LqStudyStudentUpInput.cs 0 → 100644
  1 +using System;
  2 +using System.ComponentModel.DataAnnotations;
  3 +
  4 +namespace NCC.Extend.Entitys.Dto.LqStudyStudent
  5 +{
  6 + /// <summary>
  7 + /// 学习学员更新输入
  8 + /// </summary>
  9 + public class LqStudyStudentUpInput : LqStudyStudentCrInput
  10 + {
  11 + /// <summary>
  12 + /// 学员ID
  13 + /// </summary>
  14 + [Required(ErrorMessage = "学员ID不能为空")]
  15 + [StringLength(50, ErrorMessage = "学员ID长度不能超过50个字符")]
  16 + [Display(Name = "学员ID")]
  17 + public string Id { get; set; }
  18 + }
  19 +}
... ...
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqXhHyhk/LqXhHyhkListOutput.cs
... ... @@ -59,6 +59,7 @@ namespace NCC.Extend.Entitys.Dto.LqXhHyhk
59 59 /// </summary>
60 60 public string xfje { get; set; }
61 61  
  62 +
62 63 /// <summary>
63 64 /// 手工费用
64 65 /// </summary>
... ...
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqXhHyhk/LqXhHyhkListQueryInput.cs
... ... @@ -74,5 +74,10 @@ namespace NCC.Extend.Entitys.Dto.LqXhHyhk
74 74 /// </summary>
75 75 public string czry { get; set; }
76 76  
  77 + /// <summary>
  78 + /// 是否有效
  79 + /// </summary>
  80 + public int isEffective { get; set; } = 0;
  81 +
77 82 }
78 83 }
... ...
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqXmzl/LqXmzlStatisticsInput.cs 0 → 100644
  1 +using System;
  2 +
  3 +namespace NCC.Extend.Entitys.Dto.LqXmzl
  4 +{
  5 + /// <summary>
  6 + /// 品项维度统计输入参数
  7 + /// </summary>
  8 + public class LqXmzlStatisticsInput
  9 + {
  10 + /// <summary>
  11 + /// 开始时间
  12 + /// </summary>
  13 + public DateTime? StartTime { get; set; }
  14 +
  15 + /// <summary>
  16 + /// 结束时间
  17 + /// </summary>
  18 + public DateTime? EndTime { get; set; }
  19 +
  20 + /// <summary>
  21 + /// 门店ID
  22 + /// </summary>
  23 + public string StoreId { get; set; }
  24 +
  25 + /// <summary>
  26 + /// 品项分类
  27 + /// </summary>
  28 + public string Category { get; set; }
  29 +
  30 + /// <summary>
  31 + /// 品项ID(单个品项统计)
  32 + /// </summary>
  33 + public string ItemId { get; set; }
  34 + }
  35 +}
... ...
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqXmzl/LqXmzlStatisticsOutput.cs 0 → 100644
  1 +using System;
  2 +
  3 +namespace NCC.Extend.Entitys.Dto.LqXmzl
  4 +{
  5 + /// <summary>
  6 + /// 品项维度统计输出参数
  7 + /// </summary>
  8 + public class LqXmzlStatisticsOutput
  9 + {
  10 + /// <summary>
  11 + /// 品项ID
  12 + /// </summary>
  13 + public string ItemId { get; set; }
  14 +
  15 + /// <summary>
  16 + /// 品项名称
  17 + /// </summary>
  18 + public string ItemName { get; set; }
  19 +
  20 + /// <summary>
  21 + /// 品项编号
  22 + /// </summary>
  23 + public string ItemNumber { get; set; }
  24 +
  25 + /// <summary>
  26 + /// 开卡业绩
  27 + /// </summary>
  28 + public decimal BillingAmount { get; set; }
  29 +
  30 + /// <summary>
  31 + /// 开卡业绩占比
  32 + /// </summary>
  33 + public decimal BillingAmountRatio { get; set; }
  34 +
  35 + /// <summary>
  36 + /// 购买总人数
  37 + /// </summary>
  38 + public int TotalBuyers { get; set; }
  39 +
  40 + /// <summary>
  41 + /// 品项占比
  42 + /// </summary>
  43 + public decimal ItemRatio { get; set; }
  44 +
  45 + /// <summary>
  46 + /// 复购人数
  47 + /// </summary>
  48 + public int RepeatBuyers { get; set; }
  49 +
  50 + /// <summary>
  51 + /// 复购率
  52 + /// </summary>
  53 + public decimal RepeatBuyRate { get; set; }
  54 +
  55 + /// <summary>
  56 + /// 消耗业绩
  57 + /// </summary>
  58 + public decimal ConsumeAmount { get; set; }
  59 +
  60 + /// <summary>
  61 + /// 消耗占比
  62 + /// </summary>
  63 + public decimal ConsumeAmountRatio { get; set; }
  64 +
  65 + /// <summary>
  66 + /// 消耗购买次数
  67 + /// </summary>
  68 + public int ConsumePurchaseCount { get; set; }
  69 +
  70 + /// <summary>
  71 + /// 消耗赠送次数
  72 + /// </summary>
  73 + public int ConsumeGiftCount { get; set; }
  74 +
  75 + /// <summary>
  76 + /// 消耗体验次数
  77 + /// </summary>
  78 + public int ConsumeExperienceCount { get; set; }
  79 +
  80 + /// <summary>
  81 + /// 退卡业绩
  82 + /// </summary>
  83 + public decimal RefundAmount { get; set; }
  84 +
  85 + /// <summary>
  86 + /// 退卡次数
  87 + /// </summary>
  88 + public int RefundCount { get; set; }
  89 + }
  90 +}
... ...
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_card_transfer_log/LqCardTransferLogEntity.cs 0 → 100644
  1 +using System;
  2 +using NCC.Common.Const;
  3 +using SqlSugar;
  4 +
  5 +namespace NCC.Extend.Entitys.lq_card_transfer_log
  6 +{
  7 + /// <summary>
  8 + /// 转卡日志
  9 + /// </summary>
  10 + [SugarTable("lq_card_transfer_log")]
  11 + [Tenant(ClaimConst.TENANT_ID)]
  12 + public class LqCardTransferLogEntity
  13 + {
  14 + /// <summary>
  15 + /// 主键ID
  16 + /// </summary>
  17 + [SugarColumn(ColumnName = "F_Id", IsPrimaryKey = true)]
  18 + public string Id { get; set; }
  19 +
  20 + /// <summary>
  21 + /// 退卡ID
  22 + /// </summary>
  23 + [SugarColumn(ColumnName = "F_RefundCardId")]
  24 + public string RefundCardId { get; set; }
  25 +
  26 + /// <summary>
  27 + /// 开卡ID
  28 + /// </summary>
  29 + [SugarColumn(ColumnName = "F_BillingCardId")]
  30 + public string BillingCardId { get; set; }
  31 +
  32 + /// <summary>
  33 + /// 转卡人会员ID
  34 + /// </summary>
  35 + [SugarColumn(ColumnName = "F_TransferFromMemberId")]
  36 + public string TransferFromMemberId { get; set; }
  37 +
  38 + /// <summary>
  39 + /// 被转卡人会员ID
  40 + /// </summary>
  41 + [SugarColumn(ColumnName = "F_TransferToMemberId")]
  42 + public string TransferToMemberId { get; set; }
  43 +
  44 + /// <summary>
  45 + /// 转卡总金额
  46 + /// </summary>
  47 + [SugarColumn(ColumnName = "F_TransferAmount")]
  48 + public decimal TransferAmount { get; set; }
  49 +
  50 + /// <summary>
  51 + /// 转卡时间
  52 + /// </summary>
  53 + [SugarColumn(ColumnName = "F_TransferTime")]
  54 + public DateTime TransferTime { get; set; }
  55 +
  56 + /// <summary>
  57 + /// 操作人ID
  58 + /// </summary>
  59 + [SugarColumn(ColumnName = "F_OperatorId")]
  60 + public string OperatorId { get; set; }
  61 +
  62 +
  63 + /// <summary>
  64 + /// 备注信息
  65 + /// </summary>
  66 + [SugarColumn(ColumnName = "F_Remarks")]
  67 + public string Remarks { get; set; }
  68 +
  69 + /// <summary>
  70 + /// 创建时间
  71 + /// </summary>
  72 + [SugarColumn(ColumnName = "F_CreateTime")]
  73 + public DateTime? CreateTime { get; set; }
  74 +
  75 + /// <summary>
  76 + /// 更新时间
  77 + /// </summary>
  78 + [SugarColumn(ColumnName = "F_UpdateTime")]
  79 + public DateTime? UpdateTime { get; set; }
  80 +
  81 + /// <summary>
  82 + /// 是否有效
  83 + /// </summary>
  84 + [SugarColumn(ColumnName = "F_IsEffective")]
  85 + public int IsEffective { get; set; }
  86 + }
  87 +}
... ...
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_hytk_hytk/LqHytkHytkEntity.cs
... ... @@ -67,6 +67,12 @@ namespace NCC.Extend.Entitys.lq_hytk_hytk
67 67 public decimal? Tkje { get; set; }
68 68  
69 69 /// <summary>
  70 + /// 实退金额
  71 + /// </summary>
  72 + [SugarColumn(ColumnName = "F_ActualRefundAmount")]
  73 + public decimal? ActualRefundAmount { get; set; }
  74 +
  75 + /// <summary>
70 76 /// 手工费用
71 77 /// </summary>
72 78 [SugarColumn(ColumnName = "sgfy")]
... ...
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_inventory/LqInventoryEntity.cs 0 → 100644
  1 +using System;
  2 +using NCC.Common.Const;
  3 +using SqlSugar;
  4 +
  5 +namespace NCC.Extend.Entitys.lq_inventory
  6 +{
  7 + /// <summary>
  8 + /// 库存表
  9 + /// </summary>
  10 + [SugarTable("lq_inventory")]
  11 + [Tenant(ClaimConst.TENANT_ID)]
  12 + public class LqInventoryEntity
  13 + {
  14 + /// <summary>
  15 + /// 库存ID
  16 + /// </summary>
  17 + [SugarColumn(ColumnName = "F_Id", IsPrimaryKey = true)]
  18 + public string Id { get; set; }
  19 +
  20 + /// <summary>
  21 + /// 产品名称
  22 + /// </summary>
  23 + [SugarColumn(ColumnName = "F_ProductName")]
  24 + public string ProductName { get; set; }
  25 +
  26 + /// <summary>
  27 + /// 价格
  28 + /// </summary>
  29 + [SugarColumn(ColumnName = "F_Price")]
  30 + public decimal Price { get; set; }
  31 +
  32 + /// <summary>
  33 + /// 数量
  34 + /// </summary>
  35 + [SugarColumn(ColumnName = "F_Quantity")]
  36 + public int Quantity { get; set; } = 0;
  37 +
  38 + /// <summary>
  39 + /// 产品类别
  40 + /// </summary>
  41 + [SugarColumn(ColumnName = "F_ProductCategory")]
  42 + public string ProductCategory { get; set; }
  43 +
  44 + /// <summary>
  45 + /// 归属部门ID
  46 + /// </summary>
  47 + [SugarColumn(ColumnName = "F_DepartmentId")]
  48 + public string DepartmentId { get; set; }
  49 +
  50 + /// <summary>
  51 + /// 标准单位
  52 + /// </summary>
  53 + [SugarColumn(ColumnName = "F_StandardUnit")]
  54 + public string StandardUnit { get; set; }
  55 +
  56 + /// <summary>
  57 + /// 创建人ID
  58 + /// </summary>
  59 + [SugarColumn(ColumnName = "F_CreateUser")]
  60 + public string CreateUser { get; set; }
  61 +
  62 + /// <summary>
  63 + /// 创建时间
  64 + /// </summary>
  65 + [SugarColumn(ColumnName = "F_CreateTime")]
  66 + public DateTime CreateTime { get; set; }
  67 +
  68 + /// <summary>
  69 + /// 更新人ID
  70 + /// </summary>
  71 + [SugarColumn(ColumnName = "F_UpdateUser")]
  72 + public string UpdateUser { get; set; }
  73 +
  74 + /// <summary>
  75 + /// 更新时间
  76 + /// </summary>
  77 + [SugarColumn(ColumnName = "F_UpdateTime")]
  78 + public DateTime? UpdateTime { get; set; }
  79 +
  80 + /// <summary>
  81 + /// 是否有效(1:有效 0:无效)
  82 + /// </summary>
  83 + [SugarColumn(ColumnName = "F_IsEffective")]
  84 + public int IsEffective { get; set; } = 1;
  85 + }
  86 +}
... ...
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_inventory_usage/LqInventoryUsageEntity.cs 0 → 100644
  1 +using System;
  2 +using NCC.Common.Const;
  3 +using SqlSugar;
  4 +
  5 +namespace NCC.Extend.Entitys.lq_inventory_usage
  6 +{
  7 + /// <summary>
  8 + /// 库存使用记录表
  9 + /// </summary>
  10 + [SugarTable("lq_inventory_usage")]
  11 + [Tenant(ClaimConst.TENANT_ID)]
  12 + public class LqInventoryUsageEntity
  13 + {
  14 + /// <summary>
  15 + /// 使用记录ID
  16 + /// </summary>
  17 + [SugarColumn(ColumnName = "F_Id", IsPrimaryKey = true)]
  18 + public string Id { get; set; }
  19 +
  20 + /// <summary>
  21 + /// 产品ID
  22 + /// </summary>
  23 + [SugarColumn(ColumnName = "F_ProductId")]
  24 + public string ProductId { get; set; }
  25 +
  26 + /// <summary>
  27 + /// 门店ID
  28 + /// </summary>
  29 + [SugarColumn(ColumnName = "F_StoreId")]
  30 + public string StoreId { get; set; }
  31 +
  32 + /// <summary>
  33 + /// 使用时间
  34 + /// </summary>
  35 + [SugarColumn(ColumnName = "F_UsageTime")]
  36 + public DateTime UsageTime { get; set; }
  37 +
  38 + /// <summary>
  39 + /// 使用数量
  40 + /// </summary>
  41 + [SugarColumn(ColumnName = "F_UsageQuantity")]
  42 + public int UsageQuantity { get; set; }
  43 +
  44 + /// <summary>
  45 + /// 关联消耗ID
  46 + /// </summary>
  47 + [SugarColumn(ColumnName = "F_RelatedConsumeId")]
  48 + public string RelatedConsumeId { get; set; }
  49 +
  50 + /// <summary>
  51 + /// 创建人ID
  52 + /// </summary>
  53 + [SugarColumn(ColumnName = "F_CreateUser")]
  54 + public string CreateUser { get; set; }
  55 +
  56 + /// <summary>
  57 + /// 创建时间
  58 + /// </summary>
  59 + [SugarColumn(ColumnName = "F_CreateTime")]
  60 + public DateTime CreateTime { get; set; }
  61 +
  62 + /// <summary>
  63 + /// 更新人ID
  64 + /// </summary>
  65 + [SugarColumn(ColumnName = "F_UpdateUser")]
  66 + public string UpdateUser { get; set; }
  67 +
  68 + /// <summary>
  69 + /// 更新时间
  70 + /// </summary>
  71 + [SugarColumn(ColumnName = "F_UpdateTime")]
  72 + public DateTime? UpdateTime { get; set; }
  73 +
  74 + /// <summary>
  75 + /// 是否有效(1:有效 0:无效)
  76 + /// </summary>
  77 + [SugarColumn(ColumnName = "F_IsEffective")]
  78 + public int IsEffective { get; set; } = 1;
  79 + }
  80 +}
... ...
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_statistics_store_total_performance/LqStatisticsStoreTotalPerformanceEntity.cs
... ... @@ -90,6 +90,18 @@ namespace NCC.Extend.Entitys.lq_statistics_store_total_performance
90 90 public decimal UpgradeOrderPerformance { get; set; }
91 91  
92 92 /// <summary>
  93 + /// 退款业绩
  94 + /// </summary>
  95 + [SugarColumn(ColumnName = "F_RefundAmount")]
  96 + public decimal RefundAmount { get; set; }
  97 +
  98 + /// <summary>
  99 + /// 退款次数
  100 + /// </summary>
  101 + [SugarColumn(ColumnName = "F_RefundCount")]
  102 + public int RefundCount { get; set; }
  103 +
  104 + /// <summary>
93 105 /// 创建时间
94 106 /// </summary>
95 107 [SugarColumn(ColumnName = "F_CreateTime")]
... ...
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_study_class/LqStudyClassEntity.cs 0 → 100644
  1 +using System;
  2 +using NCC.Common.Const;
  3 +using SqlSugar;
  4 +
  5 +namespace NCC.Extend.Entitys.lq_study_class
  6 +{
  7 + /// <summary>
  8 + /// 学习班级表
  9 + /// </summary>
  10 + [SugarTable("lq_study_class")]
  11 + [Tenant(ClaimConst.TENANT_ID)]
  12 + public class LqStudyClassEntity
  13 + {
  14 + /// <summary>
  15 + /// 班级ID
  16 + /// </summary>
  17 + [SugarColumn(ColumnName = "F_Id", IsPrimaryKey = true)]
  18 + public string Id { get; set; }
  19 +
  20 + /// <summary>
  21 + /// 班级名称
  22 + /// </summary>
  23 + [SugarColumn(ColumnName = "F_ClassName")]
  24 + public string ClassName { get; set; }
  25 +
  26 + /// <summary>
  27 + /// 任教老师ID
  28 + /// </summary>
  29 + [SugarColumn(ColumnName = "F_TeacherId")]
  30 + public string TeacherId { get; set; }
  31 +
  32 + /// <summary>
  33 + /// 开始时间
  34 + /// </summary>
  35 + [SugarColumn(ColumnName = "F_StartTime")]
  36 + public DateTime StartTime { get; set; }
  37 +
  38 + /// <summary>
  39 + /// 结束时间
  40 + /// </summary>
  41 + [SugarColumn(ColumnName = "F_EndTime")]
  42 + public DateTime EndTime { get; set; }
  43 +
  44 + /// <summary>
  45 + /// 备注
  46 + /// </summary>
  47 + [SugarColumn(ColumnName = "F_Remark")]
  48 + public string Remark { get; set; }
  49 +
  50 + /// <summary>
  51 + /// 创建人ID
  52 + /// </summary>
  53 + [SugarColumn(ColumnName = "F_CreateUser")]
  54 + public string CreateUser { get; set; }
  55 +
  56 + /// <summary>
  57 + /// 创建时间
  58 + /// </summary>
  59 + [SugarColumn(ColumnName = "F_CreateTime")]
  60 + public DateTime CreateTime { get; set; }
  61 +
  62 + /// <summary>
  63 + /// 更新人ID
  64 + /// </summary>
  65 + [SugarColumn(ColumnName = "F_UpdateUser")]
  66 + public string UpdateUser { get; set; }
  67 +
  68 + /// <summary>
  69 + /// 更新时间
  70 + /// </summary>
  71 + [SugarColumn(ColumnName = "F_UpdateTime")]
  72 + public DateTime? UpdateTime { get; set; }
  73 +
  74 + /// <summary>
  75 + /// 是否有效(1:有效 0:无效)
  76 + /// </summary>
  77 + [SugarColumn(ColumnName = "F_IsEffective")]
  78 + public int IsEffective { get; set; } = 1;
  79 + }
  80 +}
... ...
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_study_record/LqStudyRecordEntity.cs 0 → 100644
  1 +using System;
  2 +using NCC.Common.Const;
  3 +using SqlSugar;
  4 +
  5 +namespace NCC.Extend.Entitys.lq_study_record
  6 +{
  7 + /// <summary>
  8 + /// 学习记录表
  9 + /// </summary>
  10 + [SugarTable("lq_study_record")]
  11 + [Tenant(ClaimConst.TENANT_ID)]
  12 + public class LqStudyRecordEntity
  13 + {
  14 + /// <summary>
  15 + /// 学习记录ID
  16 + /// </summary>
  17 + [SugarColumn(ColumnName = "F_Id", IsPrimaryKey = true)]
  18 + public string Id { get; set; }
  19 +
  20 + /// <summary>
  21 + /// 员工姓名
  22 + /// </summary>
  23 + [SugarColumn(ColumnName = "F_EmployeeName")]
  24 + public string EmployeeName { get; set; }
  25 +
  26 + /// <summary>
  27 + /// 员工ID
  28 + /// </summary>
  29 + [SugarColumn(ColumnName = "F_EmployeeId")]
  30 + public string EmployeeId { get; set; }
  31 +
  32 + /// <summary>
  33 + /// 学习类型
  34 + /// </summary>
  35 + [SugarColumn(ColumnName = "F_StudyType")]
  36 + public string StudyType { get; set; }
  37 +
  38 + /// <summary>
  39 + /// 交通费
  40 + /// </summary>
  41 + [SugarColumn(ColumnName = "F_TransportFee")]
  42 + public decimal? TransportFee { get; set; }
  43 +
  44 + /// <summary>
  45 + /// 学习日期
  46 + /// </summary>
  47 + [SugarColumn(ColumnName = "F_StudyDate")]
  48 + public DateTime StudyDate { get; set; }
  49 +
  50 + /// <summary>
  51 + /// 当日状态
  52 + /// </summary>
  53 + [SugarColumn(ColumnName = "F_DailyStatus")]
  54 + public string DailyStatus { get; set; }
  55 +
  56 + /// <summary>
  57 + /// 备注
  58 + /// </summary>
  59 + [SugarColumn(ColumnName = "F_Remark")]
  60 + public string Remark { get; set; }
  61 +
  62 + /// <summary>
  63 + /// 是否下店协助(1:是 0:否)
  64 + /// </summary>
  65 + [SugarColumn(ColumnName = "F_IsStoreAssist")]
  66 + public int IsStoreAssist { get; set; } = 0;
  67 +
  68 + /// <summary>
  69 + /// 下店门店ID
  70 + /// </summary>
  71 + [SugarColumn(ColumnName = "F_StoreId")]
  72 + public string StoreId { get; set; }
  73 +
  74 + /// <summary>
  75 + /// 下店门店名称
  76 + /// </summary>
  77 + [SugarColumn(ColumnName = "F_StoreName")]
  78 + public string StoreName { get; set; }
  79 +
  80 + /// <summary>
  81 + /// 创建人ID
  82 + /// </summary>
  83 + [SugarColumn(ColumnName = "F_CreateUser")]
  84 + public string CreateUser { get; set; }
  85 +
  86 + /// <summary>
  87 + /// 创建时间
  88 + /// </summary>
  89 + [SugarColumn(ColumnName = "F_CreateTime")]
  90 + public DateTime CreateTime { get; set; }
  91 +
  92 + /// <summary>
  93 + /// 更新人ID
  94 + /// </summary>
  95 + [SugarColumn(ColumnName = "F_UpdateUser")]
  96 + public string UpdateUser { get; set; }
  97 +
  98 + /// <summary>
  99 + /// 更新时间
  100 + /// </summary>
  101 + [SugarColumn(ColumnName = "F_UpdateTime")]
  102 + public DateTime? UpdateTime { get; set; }
  103 +
  104 + /// <summary>
  105 + /// 是否有效(1:有效 0:无效)
  106 + /// </summary>
  107 + [SugarColumn(ColumnName = "F_IsEffective")]
  108 + public int IsEffective { get; set; } = 1;
  109 + }
  110 +}
... ...
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_study_student/LqStudyStudentEntity.cs 0 → 100644
  1 +using System;
  2 +using NCC.Common.Const;
  3 +using SqlSugar;
  4 +
  5 +namespace NCC.Extend.Entitys.lq_study_student
  6 +{
  7 + /// <summary>
  8 + /// 学习学员表
  9 + /// </summary>
  10 + [SugarTable("lq_study_student")]
  11 + [Tenant(ClaimConst.TENANT_ID)]
  12 + public class LqStudyStudentEntity
  13 + {
  14 + /// <summary>
  15 + /// 学员ID
  16 + /// </summary>
  17 + [SugarColumn(ColumnName = "F_Id", IsPrimaryKey = true)]
  18 + public string Id { get; set; }
  19 +
  20 + /// <summary>
  21 + /// 员工姓名
  22 + /// </summary>
  23 + [SugarColumn(ColumnName = "F_EmployeeName")]
  24 + public string EmployeeName { get; set; }
  25 +
  26 + /// <summary>
  27 + /// 员工电话
  28 + /// </summary>
  29 + [SugarColumn(ColumnName = "F_EmployeePhone")]
  30 + public string EmployeePhone { get; set; }
  31 +
  32 + /// <summary>
  33 + /// 员工ID
  34 + /// </summary>
  35 + [SugarColumn(ColumnName = "F_EmployeeId")]
  36 + public string EmployeeId { get; set; }
  37 +
  38 + /// <summary>
  39 + /// 入院时间
  40 + /// </summary>
  41 + [SugarColumn(ColumnName = "F_AdmissionTime")]
  42 + public DateTime AdmissionTime { get; set; }
  43 +
  44 + /// <summary>
  45 + /// 班级ID
  46 + /// </summary>
  47 + [SugarColumn(ColumnName = "F_ClassId")]
  48 + public string ClassId { get; set; }
  49 +
  50 + /// <summary>
  51 + /// 所属班级
  52 + /// </summary>
  53 + [SugarColumn(ColumnName = "F_ClassName")]
  54 + public string ClassName { get; set; }
  55 +
  56 + /// <summary>
  57 + /// HR归属
  58 + /// </summary>
  59 + [SugarColumn(ColumnName = "F_HrBelong")]
  60 + public string HrBelong { get; set; }
  61 +
  62 + /// <summary>
  63 + /// 创建人ID
  64 + /// </summary>
  65 + [SugarColumn(ColumnName = "F_CreateUser")]
  66 + public string CreateUser { get; set; }
  67 +
  68 + /// <summary>
  69 + /// 创建时间
  70 + /// </summary>
  71 + [SugarColumn(ColumnName = "F_CreateTime")]
  72 + public DateTime CreateTime { get; set; }
  73 +
  74 + /// <summary>
  75 + /// 更新人ID
  76 + /// </summary>
  77 + [SugarColumn(ColumnName = "F_UpdateUser")]
  78 + public string UpdateUser { get; set; }
  79 +
  80 + /// <summary>
  81 + /// 更新时间
  82 + /// </summary>
  83 + [SugarColumn(ColumnName = "F_UpdateTime")]
  84 + public DateTime? UpdateTime { get; set; }
  85 +
  86 + /// <summary>
  87 + /// 是否有效(1:有效 0:无效)
  88 + /// </summary>
  89 + [SugarColumn(ColumnName = "F_IsEffective")]
  90 + public int IsEffective { get; set; } = 1;
  91 +
  92 + /// <summary>
  93 + /// 删除标记(0:未删除 1:已删除)
  94 + /// </summary>
  95 + [SugarColumn(ColumnName = "F_DeleteMark")]
  96 + public int? DeleteMark { get; set; }
  97 + }
  98 +}
... ...
netcore/src/Modularity/Extend/NCC.Extend.Interfaces/ILqCardTransferLogService.cs 0 → 100644
  1 +using NCC.Extend.Entitys.Dto.LqCardTransferLog;
  2 +
  3 +namespace NCC.Extend.Interfaces
  4 +{
  5 + /// <summary>
  6 + /// 转卡日志服务接口
  7 + /// </summary>
  8 + public interface ILqCardTransferLogService
  9 + {
  10 + // 接口方法将在Service实现中定义
  11 + }
  12 +}
... ...
netcore/src/Modularity/Extend/NCC.Extend.Interfaces/LqInventory/ILqInventoryService.cs 0 → 100644
  1 +using System.Threading.Tasks;
  2 +using NCC.Extend.Entitys.Dto.LqInventory;
  3 +using NCC.Common.Filter;
  4 +
  5 +namespace NCC.Extend.Interfaces.LqInventory
  6 +{
  7 + /// <summary>
  8 + /// 库存服务接口
  9 + /// </summary>
  10 + public interface ILqInventoryService
  11 + {
  12 + }
  13 +}
... ...
netcore/src/Modularity/Extend/NCC.Extend.Interfaces/LqInventoryUsage/ILqInventoryUsageService.cs 0 → 100644
  1 +using System.Threading.Tasks;
  2 +using NCC.Extend.Entitys.Dto.LqInventoryUsage;
  3 +using NCC.Common.Filter;
  4 +
  5 +namespace NCC.Extend.Interfaces.LqInventoryUsage
  6 +{
  7 + /// <summary>
  8 + /// 库存使用记录服务接口
  9 + /// </summary>
  10 + public interface ILqInventoryUsageService
  11 + {
  12 + /// <summary>
  13 + /// 添加库存使用记录
  14 + /// </summary>
  15 + /// <param name="input">创建输入</param>
  16 + /// <returns></returns>
  17 + Task CreateAsync(LqInventoryUsageCrInput input);
  18 +
  19 + /// <summary>
  20 + /// 作废库存使用记录
  21 + /// </summary>
  22 + /// <param name="id">使用记录ID</param>
  23 + /// <param name="remarks">作废备注</param>
  24 + /// <returns></returns>
  25 + Task CancelAsync(string id, string remarks = null);
  26 +
  27 + /// <summary>
  28 + /// 获取使用记录列表
  29 + /// </summary>
  30 + /// <param name="input">查询输入</param>
  31 + /// <returns></returns>
  32 + Task<dynamic> GetListAsync(LqInventoryUsageListQueryInput input);
  33 +
  34 + /// <summary>
  35 + /// 统计时间周期内每个产品的使用数量
  36 + /// </summary>
  37 + /// <param name="input">统计查询输入</param>
  38 + /// <returns></returns>
  39 + Task<dynamic> GetProductUsageStatisticsAsync(LqInventoryUsageStatisticsInput input);
  40 +
  41 + /// <summary>
  42 + /// 统计时间周期内每个门店的使用情况
  43 + /// </summary>
  44 + /// <param name="input">统计查询输入</param>
  45 + /// <returns></returns>
  46 + Task<dynamic> GetStoreUsageStatisticsAsync(LqInventoryUsageStatisticsInput input);
  47 +
  48 + /// <summary>
  49 + /// 统计时间周期内使用趋势
  50 + /// </summary>
  51 + /// <param name="input">统计查询输入</param>
  52 + /// <returns></returns>
  53 + Task<dynamic> GetUsageTrendStatisticsAsync(LqInventoryUsageStatisticsInput input);
  54 +
  55 + /// <summary>
  56 + /// 统计产品使用排行榜
  57 + /// </summary>
  58 + /// <param name="input">统计查询输入</param>
  59 + /// <returns></returns>
  60 + Task<dynamic> GetProductUsageRankingAsync(LqInventoryUsageStatisticsInput input);
  61 + }
  62 +}
... ...
netcore/src/Modularity/Extend/NCC.Extend.Interfaces/LqStudyClass/ILqStudyClassService.cs 0 → 100644
  1 +using System.Threading.Tasks;
  2 +using NCC.Extend.Entitys.Dto.LqStudyClass;
  3 +using NCC.Common.Filter;
  4 +
  5 +namespace NCC.Extend.Interfaces.LqStudyClass
  6 +{
  7 + /// <summary>
  8 + /// 学习班级服务接口
  9 + /// </summary>
  10 + public interface ILqStudyClassService
  11 + {
  12 + /// <summary>
  13 + /// 创建学习班级并添加学员
  14 + /// </summary>
  15 + /// <param name="input">创建输入</param>
  16 + /// <returns></returns>
  17 + Task<dynamic> CreateClassWithStudentsAsync(LqStudyClassCreateWithStudentsInput input);
  18 +
  19 + /// <summary>
  20 + /// 向现有班级添加学员
  21 + /// </summary>
  22 + /// <param name="input">添加学员输入</param>
  23 + /// <returns></returns>
  24 + Task<dynamic> AddStudentsToClassAsync(LqStudyClassAddStudentsInput input);
  25 +
  26 + /// <summary>
  27 + /// 获取所有班级列表
  28 + /// </summary>
  29 + /// <param name="input">查询输入</param>
  30 + /// <returns></returns>
  31 + Task<dynamic> GetClassListAsync(LqStudyClassListQueryInput input);
  32 +
  33 + /// <summary>
  34 + /// 获取班级下所有学员信息
  35 + /// </summary>
  36 + /// <param name="input">查询输入</param>
  37 + /// <returns></returns>
  38 + Task<dynamic> GetStudentListByClassIdAsync(LqStudyStudentListQueryInput input);
  39 +
  40 + /// <summary>
  41 + /// 添加学习记录
  42 + /// </summary>
  43 + /// <param name="input">学习记录输入</param>
  44 + /// <returns></returns>
  45 + Task AddStudyRecordAsync(LqStudyRecordCreateInput input);
  46 +
  47 + /// <summary>
  48 + /// 获取学习记录列表
  49 + /// </summary>
  50 + /// <param name="input">查询输入</param>
  51 + /// <returns></returns>
  52 + Task<dynamic> GetStudyRecordListAsync(LqStudyRecordListQueryInput input);
  53 + }
  54 +}
... ...
netcore/src/Modularity/Extend/NCC.Extend/LqCardTransferLogService.cs 0 → 100644
  1 +using System;
  2 +using System.Linq;
  3 +using System.Threading.Tasks;
  4 +using Microsoft.AspNetCore.Mvc;
  5 +using Microsoft.Extensions.Logging;
  6 +using NCC.Common.Core.Manager;
  7 +using NCC.Common.Filter;
  8 +using NCC.Dependency;
  9 +using NCC.DynamicApiController;
  10 +using NCC.Extend.Entitys.Dto.LqCardTransferLog;
  11 +using NCC.Extend.Entitys.lq_card_transfer_log;
  12 +using NCC.Extend.Interfaces;
  13 +using NCC.FriendlyException;
  14 +using SqlSugar;
  15 +
  16 +namespace NCC.Extend.LqCardTransferLog
  17 +{
  18 + /// <summary>
  19 + /// 转卡日志服务
  20 + /// </summary>
  21 + [ApiDescriptionSettings(Tag = "绿纤转卡日志服务", Name = "LqCardTransferLog", Order = 100)]
  22 + [Route("api/Extend/[controller]")]
  23 + public class LqCardTransferLogService : IDynamicApiController, ILqCardTransferLogService, ITransient
  24 + {
  25 + private readonly ISqlSugarClient _db;
  26 + private readonly IUserManager _userManager;
  27 + private readonly ILogger<LqCardTransferLogService> _logger;
  28 +
  29 + public LqCardTransferLogService(ISqlSugarClient db, IUserManager userManager, ILogger<LqCardTransferLogService> logger)
  30 + {
  31 + _db = db;
  32 + _userManager = userManager;
  33 + _logger = logger;
  34 + }
  35 +
  36 + #region 添加转卡日志
  37 + /// <summary>
  38 + /// 添加转卡日志
  39 + /// </summary>
  40 + /// <param name="input">转卡日志创建输入参数</param>
  41 + /// <returns>创建结果</returns>
  42 + [HttpPost("add")]
  43 + public async Task<dynamic> AddTransferLog([FromBody] LqCardTransferLogCrInput input)
  44 + {
  45 + try
  46 + {
  47 + if (input == null)
  48 + {
  49 + throw NCCException.Oh("输入参数不能为空");
  50 + }
  51 +
  52 + var entity = new LqCardTransferLogEntity
  53 + {
  54 + Id = Guid.NewGuid().ToString(),
  55 + RefundCardId = input.refundCardId,
  56 + BillingCardId = input.billingCardId,
  57 + TransferFromMemberId = input.transferFromMemberId,
  58 + TransferToMemberId = input.transferToMemberId,
  59 + TransferAmount = input.transferAmount,
  60 + TransferTime = input.transferTime,
  61 + OperatorId = input.operatorId,
  62 + Remarks = input.remarks ?? "",
  63 + CreateTime = DateTime.Now,
  64 + IsEffective = 1
  65 + };
  66 +
  67 + var result = await _db.Insertable(entity).ExecuteCommandAsync();
  68 +
  69 + return new
  70 + {
  71 + Success = true,
  72 + Message = "转卡日志创建成功",
  73 + Data = new { Id = entity.Id }
  74 + };
  75 + }
  76 + catch (Exception ex)
  77 + {
  78 + throw NCCException.Oh($"创建转卡日志失败: {ex.Message}");
  79 + }
  80 + }
  81 + #endregion
  82 +
  83 + #region 获取转卡日志列表
  84 + /// <summary>
  85 + /// 获取转卡日志列表
  86 + /// </summary>
  87 + /// <param name="input">查询输入参数</param>
  88 + /// <returns>转卡日志列表</returns>
  89 + [HttpGet("")]
  90 + public async Task<dynamic> GetList([FromQuery] LqCardTransferLogListQueryInput input)
  91 + {
  92 + try
  93 + {
  94 + var result = await _db.Queryable<LqCardTransferLogEntity>()
  95 + .WhereIF(input.isEffective != 0, x => x.IsEffective == input.isEffective)
  96 + .WhereIF(!string.IsNullOrEmpty(input.transferFromMemberId), x => x.TransferFromMemberId == input.transferFromMemberId)
  97 + .WhereIF(!string.IsNullOrEmpty(input.transferToMemberId), x => x.TransferToMemberId == input.transferToMemberId)
  98 + .WhereIF(!string.IsNullOrEmpty(input.operatorId), x => x.OperatorId == input.operatorId)
  99 + .WhereIF(input.transferStartTime.HasValue, x => x.TransferTime >= input.transferStartTime.Value)
  100 + .WhereIF(input.transferEndTime.HasValue, x => x.TransferTime <= input.transferEndTime.Value)
  101 + .WhereIF(input.minTransferAmount.HasValue, x => x.TransferAmount >= input.minTransferAmount.Value)
  102 + .WhereIF(input.maxTransferAmount.HasValue, x => x.TransferAmount <= input.maxTransferAmount.Value)
  103 + .WhereIF(!string.IsNullOrEmpty(input.keyword), x => x.Remarks.Contains(input.keyword))
  104 + .Select(x => new LqCardTransferLogListOutput
  105 + {
  106 + id = x.Id,
  107 + refundCardId = x.RefundCardId,
  108 + billingCardId = x.BillingCardId,
  109 + transferFromMemberId = x.TransferFromMemberId,
  110 + transferToMemberId = x.TransferToMemberId,
  111 + transferAmount = x.TransferAmount,
  112 + transferTime = x.TransferTime,
  113 + operatorId = x.OperatorId,
  114 + remarks = x.Remarks,
  115 + createTime = x.CreateTime,
  116 + updateTime = x.UpdateTime,
  117 + isEffective = x.IsEffective
  118 + })
  119 + .OrderBy(x => x.transferTime, OrderByType.Desc)
  120 + .ToPagedListAsync(input.currentPage, input.pageSize);
  121 +
  122 + return PageResult<LqCardTransferLogListOutput>.SqlSugarPageResult(result);
  123 + }
  124 + catch (Exception ex)
  125 + {
  126 + throw NCCException.Oh($"获取转卡日志列表失败: {ex.Message}");
  127 + }
  128 + }
  129 + #endregion
  130 + }
  131 +}
... ...
netcore/src/Modularity/Extend/NCC.Extend/LqHytkHytkService.cs
... ... @@ -96,6 +96,7 @@ namespace NCC.Extend.LqHytkHytk
96 96 .WhereIF(queryTksj != null, p => p.Tksj >= new DateTime(startTksj.ToDate().Year, startTksj.ToDate().Month, startTksj.ToDate().Day, 0, 0, 0))
97 97 .WhereIF(queryTksj != null, p => p.Tksj <= new DateTime(endTksj.ToDate().Year, endTksj.ToDate().Month, endTksj.ToDate().Day, 23, 59, 59))
98 98 .WhereIF(!string.IsNullOrEmpty(input.czry), p => p.Czry.Equals(input.czry))
  99 + .WhereIF(input.isEffective != 0, p => p.IsEffective == input.isEffective)
99 100 .Select(it => new LqHytkHytkListOutput
100 101 {
101 102 id = it.Id,
... ... @@ -116,6 +117,7 @@ namespace NCC.Extend.LqHytkHytk
116 117 fileUrl = it.FileUrl,
117 118 isEffective = it.IsEffective,
118 119 cancelRemark = it.CancelRemark,
  120 + actualRefundAmount = it.ActualRefundAmount
119 121 })
120 122 .MergeTable()
121 123 .OrderBy(sidx + " " + input.sort)
... ...
netcore/src/Modularity/Extend/NCC.Extend/LqInventoryService.cs 0 → 100644
  1 +using System;
  2 +using System.Threading.Tasks;
  3 +using Microsoft.AspNetCore.Mvc;
  4 +using Microsoft.Extensions.Logging;
  5 +using NCC.Common.Core.Manager;
  6 +using NCC.Common.Enum;
  7 +using NCC.Common.Filter;
  8 +using NCC.Dependency;
  9 +using NCC.DynamicApiController;
  10 +using NCC.Extend.Entitys.Dto.LqInventory;
  11 +using NCC.Extend.Entitys.Enum;
  12 +using NCC.Extend.Entitys.lq_inventory;
  13 +using NCC.Extend.Interfaces.LqInventory;
  14 +using NCC.FriendlyException;
  15 +using NCC.System.Entitys.Permission;
  16 +using SqlSugar;
  17 +using Yitter.IdGenerator;
  18 +
  19 +namespace NCC.Extend
  20 +{
  21 + /// <summary>
  22 + /// 库存服务
  23 + /// </summary>
  24 + [ApiDescriptionSettings(Tag = "绿纤库存管理", Name = "LqInventory", Order = 200)]
  25 + [Route("api/Extend/LqInventory")]
  26 + public class LqInventoryService : IDynamicApiController, ITransient, ILqInventoryService
  27 + {
  28 + private readonly IUserManager _userManager;
  29 + private readonly ILogger<LqInventoryService> _logger;
  30 + private readonly ISqlSugarClient _db;
  31 +
  32 + /// <summary>
  33 + /// 构造函数
  34 + /// </summary>
  35 + /// <param name="userManager">用户管理器</param>
  36 + /// <param name="logger">日志记录器</param>
  37 + /// <param name="db">数据库客户端</param>
  38 + public LqInventoryService(IUserManager userManager, ILogger<LqInventoryService> logger, ISqlSugarClient db)
  39 + {
  40 + _userManager = userManager;
  41 + _logger = logger;
  42 + _db = db;
  43 + }
  44 +
  45 + #region 创建库存
  46 + /// <summary>
  47 + /// 创建库存
  48 + /// </summary>
  49 + /// <param name="input">创建输入</param>
  50 + /// <returns>创建结果</returns>
  51 + [HttpPost("Create")]
  52 + public async Task CreateAsync([FromBody] LqInventoryCrInput input)
  53 + {
  54 + try
  55 + {
  56 + // 检查产品名称是否已存在
  57 + var existingProduct = await _db.Queryable<LqInventoryEntity>()
  58 + .Where(x => x.ProductName == input.ProductName && x.IsEffective == StatusEnum.有效.GetHashCode())
  59 + .FirstAsync();
  60 + if (existingProduct != null)
  61 + {
  62 + throw NCCException.Oh($"产品名称'{input.ProductName}'已存在");
  63 + }
  64 +
  65 + // 创建库存记录
  66 + var inventoryEntity = new LqInventoryEntity
  67 + {
  68 + Id = YitIdHelper.NextId().ToString(),
  69 + ProductName = input.ProductName,
  70 + Price = input.Price,
  71 + Quantity = input.Quantity,
  72 + ProductCategory = input.ProductCategory,
  73 + DepartmentId = input.DepartmentId,
  74 + StandardUnit = input.StandardUnit,
  75 + CreateUser = _userManager.UserId,
  76 + CreateTime = DateTime.Now,
  77 + IsEffective = StatusEnum.有效.GetHashCode()
  78 + };
  79 +
  80 + var isOk = await _db.Insertable(inventoryEntity).ExecuteCommandAsync();
  81 + if (!(isOk > 0)) throw NCCException.Oh(ErrorCode.COM1000);
  82 + }
  83 + catch (Exception ex)
  84 + {
  85 + _logger.LogError(ex, "创建库存失败");
  86 + throw NCCException.Oh($"创建失败:{ex.Message}");
  87 + }
  88 + }
  89 + #endregion
  90 +
  91 + #region 更新库存
  92 + /// <summary>
  93 + /// 更新库存
  94 + /// </summary>
  95 + /// <param name="input">更新输入</param>
  96 + /// <returns>更新结果</returns>
  97 + [HttpPut("Update")]
  98 + public async Task UpdateAsync([FromBody] LqInventoryUpInput input)
  99 + {
  100 + try
  101 + {
  102 + // 检查库存记录是否存在
  103 + var existingInventory = await _db.Queryable<LqInventoryEntity>()
  104 + .Where(x => x.Id == input.Id && x.IsEffective == StatusEnum.有效.GetHashCode())
  105 + .FirstAsync();
  106 +
  107 + if (existingInventory == null)
  108 + {
  109 + throw NCCException.Oh("库存记录不存在或已失效");
  110 + }
  111 +
  112 + // 检查产品名称是否与其他记录重复
  113 + var duplicateProduct = await _db.Queryable<LqInventoryEntity>()
  114 + .Where(x => x.ProductName == input.ProductName && x.Id != input.Id && x.IsEffective == StatusEnum.有效.GetHashCode())
  115 + .FirstAsync();
  116 +
  117 + if (duplicateProduct != null)
  118 + {
  119 + throw NCCException.Oh($"产品名称'{input.ProductName}'已存在");
  120 + }
  121 +
  122 + // 更新库存记录
  123 + existingInventory.ProductName = input.ProductName;
  124 + existingInventory.Price = input.Price;
  125 + existingInventory.Quantity = input.Quantity;
  126 + existingInventory.ProductCategory = input.ProductCategory;
  127 + existingInventory.DepartmentId = input.DepartmentId;
  128 + existingInventory.StandardUnit = input.StandardUnit;
  129 + existingInventory.UpdateUser = _userManager.UserId;
  130 + existingInventory.UpdateTime = DateTime.Now;
  131 +
  132 + var isOk = await _db.Updateable(existingInventory).ExecuteCommandAsync();
  133 + if (!(isOk > 0)) throw NCCException.Oh(ErrorCode.COM1000);
  134 + }
  135 + catch (Exception ex)
  136 + {
  137 + _logger.LogError(ex, "更新库存失败");
  138 + throw NCCException.Oh($"更新失败:{ex.Message}");
  139 + }
  140 + }
  141 + #endregion
  142 +
  143 + #region 获取库存列表
  144 + /// <summary>
  145 + /// 获取库存列表
  146 + /// </summary>
  147 + /// <param name="input">查询输入</param>
  148 + /// <returns>库存列表</returns>
  149 + [HttpGet("GetList")]
  150 + public async Task<dynamic> GetListAsync([FromQuery] LqInventoryListQueryInput input)
  151 + {
  152 + try
  153 + {
  154 + var sidx = input.sidx == null ? "id" : input.sidx;
  155 +
  156 + // 查询库存信息
  157 + var data = await _db.Queryable<LqInventoryEntity>()
  158 + .WhereIF(!string.IsNullOrWhiteSpace(input.ProductName), x => x.ProductName.Contains(input.ProductName))
  159 + .WhereIF(!string.IsNullOrWhiteSpace(input.ProductCategory), x => x.ProductCategory.Contains(input.ProductCategory))
  160 + .WhereIF(!string.IsNullOrWhiteSpace(input.DepartmentId), x => x.DepartmentId == input.DepartmentId)
  161 + .WhereIF(input.PriceMin.HasValue, x => x.Price >= input.PriceMin.Value)
  162 + .WhereIF(input.PriceMax.HasValue, x => x.Price <= input.PriceMax.Value)
  163 + .WhereIF(input.QuantityMin.HasValue, x => x.Quantity >= input.QuantityMin.Value)
  164 + .WhereIF(input.QuantityMax.HasValue, x => x.Quantity <= input.QuantityMax.Value)
  165 + .WhereIF(input.IsEffective.HasValue, x => x.IsEffective == input.IsEffective.Value)
  166 + .Select(x => new LqInventoryListOutput
  167 + {
  168 + id = x.Id,
  169 + productName = x.ProductName,
  170 + price = x.Price,
  171 + quantity = x.Quantity,
  172 + productCategory = x.ProductCategory,
  173 + departmentId = x.DepartmentId,
  174 + departmentName = "",
  175 + standardUnit = x.StandardUnit,
  176 + totalValue = x.Price * x.Quantity,
  177 + createUser = x.CreateUser,
  178 + createUserName = "",
  179 + createTime = x.CreateTime,
  180 + updateUser = x.UpdateUser,
  181 + updateUserName = "",
  182 + updateTime = x.UpdateTime,
  183 + isEffective = x.IsEffective
  184 + })
  185 + .MergeTable()
  186 + .OrderBy(sidx + " " + input.sort)
  187 + .ToPagedListAsync(input.currentPage, input.pageSize);
  188 +
  189 + // 补充用户名称信息
  190 + foreach (var item in data.list)
  191 + {
  192 + if (!string.IsNullOrEmpty(item.departmentId))
  193 + {
  194 + var deptUser = await _db.Queryable<UserEntity>().Where(u => u.Id == item.departmentId).FirstAsync();
  195 + item.departmentName = deptUser?.RealName ?? "";
  196 + }
  197 + if (!string.IsNullOrEmpty(item.createUser))
  198 + {
  199 + var createUser = await _db.Queryable<UserEntity>().Where(u => u.Id == item.createUser).FirstAsync();
  200 + item.createUserName = createUser?.RealName ?? "";
  201 + }
  202 + if (!string.IsNullOrEmpty(item.updateUser))
  203 + {
  204 + var updateUser = await _db.Queryable<UserEntity>().Where(u => u.Id == item.updateUser).FirstAsync();
  205 + item.updateUserName = updateUser?.RealName ?? "";
  206 + }
  207 + }
  208 + return PageResult<LqInventoryListOutput>.SqlSugarPageResult(data);
  209 + }
  210 + catch (Exception ex)
  211 + {
  212 + _logger.LogError(ex, "获取库存列表失败");
  213 + throw NCCException.Oh($"获取库存列表失败:{ex.Message}");
  214 + }
  215 + }
  216 + #endregion
  217 +
  218 + #region 获取库存详情
  219 + /// <summary>
  220 + /// 获取库存详情
  221 + /// </summary>
  222 + /// <param name="id">库存ID</param>
  223 + /// <returns>库存详情</returns>
  224 + [HttpGet("GetInfo")]
  225 + public async Task<dynamic> GetInfoAsync([FromQuery] string id)
  226 + {
  227 + try
  228 + {
  229 + if (string.IsNullOrWhiteSpace(id))
  230 + {
  231 + throw NCCException.Oh("库存ID不能为空");
  232 + }
  233 + // 查询库存信息
  234 + var inventory = await _db.Queryable<LqInventoryEntity>().Where(x => x.Id == id).FirstAsync();
  235 +
  236 + if (inventory == null)
  237 + {
  238 + throw NCCException.Oh("库存记录不存在");
  239 + }
  240 +
  241 + var result = new LqInventoryInfoOutput
  242 + {
  243 + id = inventory.Id,
  244 + productName = inventory.ProductName,
  245 + price = inventory.Price,
  246 + quantity = inventory.Quantity,
  247 + productCategory = inventory.ProductCategory,
  248 + departmentId = inventory.DepartmentId,
  249 + departmentName = "",
  250 + standardUnit = inventory.StandardUnit,
  251 + totalValue = inventory.Price * inventory.Quantity,
  252 + createUser = inventory.CreateUser,
  253 + createUserName = "",
  254 + createTime = inventory.CreateTime,
  255 + updateUser = inventory.UpdateUser,
  256 + updateUserName = "",
  257 + updateTime = inventory.UpdateTime,
  258 + isEffective = inventory.IsEffective
  259 + };
  260 +
  261 + // 补充用户名称信息
  262 + if (!string.IsNullOrEmpty(result.departmentId))
  263 + {
  264 + var deptUser = await _db.Queryable<UserEntity>().Where(u => u.Id == result.departmentId).FirstAsync();
  265 + result.departmentName = deptUser?.RealName ?? "";
  266 + }
  267 + if (!string.IsNullOrEmpty(result.createUser))
  268 + {
  269 + var createUser = await _db.Queryable<UserEntity>().Where(u => u.Id == result.createUser).FirstAsync();
  270 + result.createUserName = createUser?.RealName ?? "";
  271 + }
  272 + if (!string.IsNullOrEmpty(result.updateUser))
  273 + {
  274 + var updateUser = await _db.Queryable<UserEntity>().Where(u => u.Id == result.updateUser).FirstAsync();
  275 + result.updateUserName = updateUser?.RealName ?? "";
  276 + }
  277 +
  278 + return result;
  279 + }
  280 + catch (Exception ex)
  281 + {
  282 + _logger.LogError(ex, "获取库存详情失败");
  283 + throw NCCException.Oh($"获取库存详情失败:{ex.Message}");
  284 + }
  285 + }
  286 + #endregion
  287 +
  288 +
  289 + }
  290 +}
... ...
netcore/src/Modularity/Extend/NCC.Extend/LqInventoryUsageService.cs 0 → 100644
  1 +using System;
  2 +using System.Linq;
  3 +using System.Threading.Tasks;
  4 +using Microsoft.AspNetCore.Mvc;
  5 +using Microsoft.Extensions.Logging;
  6 +using NCC.Common.Core.Manager;
  7 +using NCC.Common.Enum;
  8 +using NCC.Common.Filter;
  9 +using NCC.Dependency;
  10 +using NCC.DynamicApiController;
  11 +using NCC.Extend.Entitys.Dto.LqInventoryUsage;
  12 +using NCC.Extend.Entitys.Enum;
  13 +using NCC.Extend.Entitys.lq_inventory;
  14 +using NCC.Extend.Entitys.lq_inventory_usage;
  15 +using NCC.Extend.Interfaces.LqInventoryUsage;
  16 +using NCC.FriendlyException;
  17 +using NCC.System.Entitys.Permission;
  18 +using SqlSugar;
  19 +using Yitter.IdGenerator;
  20 +
  21 +namespace NCC.Extend
  22 +{
  23 + /// <summary>
  24 + /// 库存使用记录服务
  25 + /// </summary>
  26 + [ApiDescriptionSettings(Tag = "绿纤库存使用记录管理", Name = "LqInventoryUsage", Order = 200)]
  27 + [Route("api/Extend/LqInventoryUsage")]
  28 + public class LqInventoryUsageService : IDynamicApiController, ITransient, ILqInventoryUsageService
  29 + {
  30 + private readonly IUserManager _userManager;
  31 + private readonly ILogger<LqInventoryUsageService> _logger;
  32 + private readonly ISqlSugarClient _db;
  33 +
  34 + /// <summary>
  35 + /// 构造函数
  36 + /// </summary>
  37 + /// <param name="userManager">用户管理器</param>
  38 + /// <param name="logger">日志记录器</param>
  39 + /// <param name="db">数据库客户端</param>
  40 + public LqInventoryUsageService(IUserManager userManager, ILogger<LqInventoryUsageService> logger, ISqlSugarClient db)
  41 + {
  42 + _userManager = userManager;
  43 + _logger = logger;
  44 + _db = db;
  45 + }
  46 +
  47 + #region 添加库存使用记录
  48 + /// <summary>
  49 + /// 添加库存使用记录
  50 + /// </summary>
  51 + /// <param name="input">创建输入</param>
  52 + /// <returns>创建结果</returns>
  53 + [HttpPost("Create")]
  54 + public async Task CreateAsync([FromBody] LqInventoryUsageCrInput input)
  55 + {
  56 + try
  57 + {
  58 + // 验证产品是否存在
  59 + var product = await _db.Queryable<LqInventoryEntity>().Where(x => x.Id == input.ProductId && x.IsEffective == StatusEnum.有效.GetHashCode()).FirstAsync();
  60 +
  61 + if (product == null)
  62 + {
  63 + throw NCCException.Oh("产品不存在或已失效");
  64 + }
  65 +
  66 + // 检查库存数量是否足够
  67 + if (product.Quantity < input.UsageQuantity)
  68 + {
  69 + throw NCCException.Oh($"库存不足,当前库存:{product.Quantity},需要数量:{input.UsageQuantity}");
  70 + }
  71 +
  72 + _db.Ado.BeginTran();
  73 +
  74 + // 创建使用记录
  75 + var usageEntity = new LqInventoryUsageEntity
  76 + {
  77 + Id = YitIdHelper.NextId().ToString(),
  78 + ProductId = input.ProductId,
  79 + StoreId = input.StoreId,
  80 + UsageTime = input.UsageTime,
  81 + UsageQuantity = input.UsageQuantity,
  82 + RelatedConsumeId = input.RelatedConsumeId,
  83 + CreateUser = _userManager.UserId,
  84 + CreateTime = DateTime.Now,
  85 + IsEffective = StatusEnum.有效.GetHashCode()
  86 + };
  87 +
  88 + var isOk = await _db.Insertable(usageEntity).ExecuteCommandAsync();
  89 + if (!(isOk > 0)) throw NCCException.Oh(ErrorCode.COM1000);
  90 +
  91 + // 更新库存数量
  92 + product.Quantity -= input.UsageQuantity;
  93 + product.UpdateUser = _userManager.UserId;
  94 + product.UpdateTime = DateTime.Now;
  95 + var updateOk = await _db.Updateable(product).ExecuteCommandAsync();
  96 + if (!(updateOk > 0)) throw NCCException.Oh(ErrorCode.COM1001);
  97 + _db.Ado.CommitTran();
  98 + }
  99 + catch (Exception ex)
  100 + {
  101 + _db.Ado.RollbackTran();
  102 + _logger.LogError(ex, "添加库存使用记录失败");
  103 + throw NCCException.Oh($"添加失败:{ex.Message}");
  104 + }
  105 + }
  106 + #endregion
  107 +
  108 + #region 作废库存使用记录
  109 + /// <summary>
  110 + /// 作废库存使用记录
  111 + /// </summary>
  112 + /// <param name="id">使用记录ID</param>
  113 + /// <param name="remarks">作废备注</param>
  114 + /// <returns>作废结果</returns>
  115 + [HttpPut("Cancel")]
  116 + public async Task CancelAsync([FromQuery] string id, [FromQuery] string remarks = null)
  117 + {
  118 + try
  119 + {
  120 + if (string.IsNullOrWhiteSpace(id))
  121 + {
  122 + throw NCCException.Oh("使用记录ID不能为空");
  123 + }
  124 +
  125 + // 检查使用记录是否存在
  126 + var usageRecord = await _db.Queryable<LqInventoryUsageEntity>().Where(x => x.Id == id && x.IsEffective == StatusEnum.有效.GetHashCode()).FirstAsync();
  127 +
  128 + if (usageRecord == null)
  129 + {
  130 + throw NCCException.Oh("使用记录不存在或已失效");
  131 + }
  132 +
  133 + _db.Ado.BeginTran();
  134 +
  135 + // 作废使用记录
  136 + usageRecord.IsEffective = StatusEnum.无效.GetHashCode();
  137 + usageRecord.UpdateUser = _userManager.UserId;
  138 + usageRecord.UpdateTime = DateTime.Now;
  139 +
  140 + var isOk = await _db.Updateable(usageRecord).ExecuteCommandAsync();
  141 + if (!(isOk > 0)) throw NCCException.Oh(ErrorCode.COM1003);
  142 + // 恢复库存数量
  143 + var product = await _db.Queryable<LqInventoryEntity>().Where(x => x.Id == usageRecord.ProductId && x.IsEffective == StatusEnum.有效.GetHashCode()).FirstAsync();
  144 + if (product != null)
  145 + {
  146 + product.Quantity += usageRecord.UsageQuantity;
  147 + product.UpdateUser = _userManager.UserId;
  148 + product.UpdateTime = DateTime.Now;
  149 + var updateOk = await _db.Updateable(product).ExecuteCommandAsync();
  150 + if (!(updateOk > 0)) throw NCCException.Oh(ErrorCode.COM1001);
  151 + }
  152 +
  153 + _db.Ado.CommitTran();
  154 + }
  155 + catch (Exception ex)
  156 + {
  157 + _db.Ado.RollbackTran();
  158 + _logger.LogError(ex, "作废库存使用记录失败");
  159 + throw NCCException.Oh($"作废失败:{ex.Message}");
  160 + }
  161 + }
  162 + #endregion
  163 +
  164 + #region 获取使用记录列表
  165 + /// <summary>
  166 + /// 获取使用记录列表
  167 + /// </summary>
  168 + /// <param name="input">查询输入</param>
  169 + /// <returns>使用记录列表</returns>
  170 + [HttpGet("GetList")]
  171 + public async Task<dynamic> GetListAsync([FromQuery] LqInventoryUsageListQueryInput input)
  172 + {
  173 + try
  174 + {
  175 + var sidx = input.sidx == null ? "id" : input.sidx;
  176 +
  177 + // 查询使用记录信息
  178 + var data = await _db.Queryable<LqInventoryUsageEntity>()
  179 + .WhereIF(!string.IsNullOrWhiteSpace(input.ProductId), x => x.ProductId == input.ProductId)
  180 + .WhereIF(!string.IsNullOrWhiteSpace(input.StoreId), x => x.StoreId == input.StoreId)
  181 + .WhereIF(input.UsageStartTime.HasValue, x => x.UsageTime >= input.UsageStartTime.Value)
  182 + .WhereIF(input.UsageEndTime.HasValue, x => x.UsageTime <= input.UsageEndTime.Value)
  183 + .WhereIF(!string.IsNullOrWhiteSpace(input.RelatedConsumeId), x => x.RelatedConsumeId == input.RelatedConsumeId)
  184 + .WhereIF(input.IsEffective.HasValue, x => x.IsEffective == input.IsEffective.Value)
  185 + .Select(x => new LqInventoryUsageListOutput
  186 + {
  187 + Id = x.Id,
  188 + ProductId = x.ProductId,
  189 + ProductName = "",
  190 + ProductCategory = "",
  191 + ProductPrice = 0,
  192 + StoreId = x.StoreId,
  193 + StoreName = "",
  194 + UsageTime = x.UsageTime,
  195 + UsageQuantity = x.UsageQuantity,
  196 + RelatedConsumeId = x.RelatedConsumeId,
  197 + CreateUser = x.CreateUser,
  198 + CreateUserName = "",
  199 + CreateTime = x.CreateTime,
  200 + UpdateUser = x.UpdateUser,
  201 + UpdateUserName = "",
  202 + UpdateTime = x.UpdateTime,
  203 + IsEffective = x.IsEffective
  204 + })
  205 + .MergeTable()
  206 + .OrderBy(sidx + " " + input.sort)
  207 + .ToPagedListAsync(input.currentPage, input.pageSize);
  208 +
  209 + // 补充产品信息和用户信息
  210 + foreach (var item in data.list)
  211 + {
  212 + if (!string.IsNullOrEmpty(item.ProductId))
  213 + {
  214 + var product = await _db.Queryable<LqInventoryEntity>().Where(p => p.Id == item.ProductId).FirstAsync();
  215 + if (product != null)
  216 + {
  217 + item.ProductName = product.ProductName;
  218 + item.ProductCategory = product.ProductCategory;
  219 + item.ProductPrice = product.Price;
  220 + }
  221 + }
  222 + if (!string.IsNullOrEmpty(item.StoreId))
  223 + {
  224 + var store = await _db.Queryable<UserEntity>().Where(u => u.Id == item.StoreId).FirstAsync();
  225 + item.StoreName = store?.RealName ?? "";
  226 + }
  227 + if (!string.IsNullOrEmpty(item.CreateUser))
  228 + {
  229 + var createUser = await _db.Queryable<UserEntity>().Where(u => u.Id == item.CreateUser).FirstAsync();
  230 + item.CreateUserName = createUser?.RealName ?? "";
  231 + }
  232 + if (!string.IsNullOrEmpty(item.UpdateUser))
  233 + {
  234 + var updateUser = await _db.Queryable<UserEntity>().Where(u => u.Id == item.UpdateUser).FirstAsync();
  235 + item.UpdateUserName = updateUser?.RealName ?? "";
  236 + }
  237 + }
  238 +
  239 + // 应用产品名称和分类的过滤条件
  240 + if (!string.IsNullOrWhiteSpace(input.ProductName) || !string.IsNullOrWhiteSpace(input.ProductCategory))
  241 + {
  242 + data.list = data.list.Where(x =>
  243 + (string.IsNullOrWhiteSpace(input.ProductName) || x.ProductName.Contains(input.ProductName)) &&
  244 + (string.IsNullOrWhiteSpace(input.ProductCategory) || x.ProductCategory.Contains(input.ProductCategory))
  245 + ).ToList();
  246 + }
  247 +
  248 + // 应用门店名称的过滤条件
  249 + if (!string.IsNullOrWhiteSpace(input.StoreName))
  250 + {
  251 + data.list = data.list.Where(x => x.StoreName.Contains(input.StoreName)).ToList();
  252 + }
  253 + return PageResult<LqInventoryUsageListOutput>.SqlSugarPageResult(data);
  254 + }
  255 + catch (Exception ex)
  256 + {
  257 + _logger.LogError(ex, "获取使用记录列表失败");
  258 + throw NCCException.Oh($"获取使用记录列表失败:{ex.Message}");
  259 + }
  260 + }
  261 + #endregion
  262 +
  263 + #region 统计时间周期内每个产品的使用数量
  264 + /// <summary>
  265 + /// 统计时间周期内每个产品的使用数量
  266 + /// </summary>
  267 + /// <param name="input">统计查询输入</param>
  268 + /// <returns>产品使用统计</returns>
  269 + [HttpPost("GetProductUsageStatistics")]
  270 + public async Task<dynamic> GetProductUsageStatisticsAsync([FromBody] LqInventoryUsageStatisticsInput input)
  271 + {
  272 + try
  273 + {
  274 + var data = await _db.Queryable<LqInventoryUsageEntity>()
  275 + .LeftJoin<LqInventoryEntity>((usage, product) => usage.ProductId == product.Id)
  276 + .Where((usage, product) => usage.UsageTime >= input.StartTime && usage.UsageTime <= input.EndTime)
  277 + .Where((usage, product) => usage.IsEffective == StatusEnum.有效.GetHashCode())
  278 + .WhereIF(!string.IsNullOrWhiteSpace(input.ProductId), (usage, product) => usage.ProductId == input.ProductId)
  279 + .WhereIF(!string.IsNullOrWhiteSpace(input.StoreId), (usage, product) => usage.StoreId == input.StoreId)
  280 + .WhereIF(!string.IsNullOrWhiteSpace(input.ProductCategory), (usage, product) => product.ProductCategory == input.ProductCategory)
  281 + .GroupBy((usage, product) => new { usage.ProductId, product.ProductName, product.ProductCategory, product.Price })
  282 + .Select((usage, product) => new ProductUsageStatisticsOutput
  283 + {
  284 + ProductId = usage.ProductId,
  285 + ProductName = product.ProductName,
  286 + ProductCategory = product.ProductCategory,
  287 + ProductPrice = product.Price,
  288 + TotalUsageQuantity = SqlFunc.AggregateSum(usage.UsageQuantity),
  289 + TotalUsageAmount = SqlFunc.AggregateSum(usage.UsageQuantity * product.Price),
  290 + UsageCount = SqlFunc.AggregateCount(usage.Id),
  291 + AverageUsageQuantity = SqlFunc.AggregateAvg(usage.UsageQuantity)
  292 + })
  293 + .ToListAsync();
  294 +
  295 + return new
  296 + {
  297 + success = true,
  298 + data = data,
  299 + total = data.Count,
  300 + message = "产品使用统计查询成功"
  301 + };
  302 + }
  303 + catch (Exception ex)
  304 + {
  305 + _logger.LogError(ex, "获取产品使用统计失败");
  306 + throw NCCException.Oh($"获取产品使用统计失败:{ex.Message}");
  307 + }
  308 + }
  309 + #endregion
  310 +
  311 + #region 统计时间周期内每个门店的使用情况
  312 + /// <summary>
  313 + /// 统计时间周期内每个门店的使用情况
  314 + /// </summary>
  315 + /// <param name="input">统计查询输入</param>
  316 + /// <returns>门店使用统计</returns>
  317 + [HttpPost("GetStoreUsageStatistics")]
  318 + public async Task<dynamic> GetStoreUsageStatisticsAsync([FromBody] LqInventoryUsageStatisticsInput input)
  319 + {
  320 + try
  321 + {
  322 + var data = await _db.Queryable<LqInventoryUsageEntity>()
  323 + .LeftJoin<LqInventoryEntity>((usage, product) => usage.ProductId == product.Id)
  324 + .LeftJoin<UserEntity>((usage, product, store) => usage.StoreId == store.Id)
  325 + .Where((usage, product, store) => usage.UsageTime >= input.StartTime && usage.UsageTime <= input.EndTime)
  326 + .Where((usage, product, store) => usage.IsEffective == StatusEnum.有效.GetHashCode())
  327 + .WhereIF(!string.IsNullOrWhiteSpace(input.ProductId), (usage, product, store) => usage.ProductId == input.ProductId)
  328 + .WhereIF(!string.IsNullOrWhiteSpace(input.StoreId), (usage, product, store) => usage.StoreId == input.StoreId)
  329 + .WhereIF(!string.IsNullOrWhiteSpace(input.ProductCategory), (usage, product, store) => product.ProductCategory == input.ProductCategory)
  330 + .GroupBy((usage, product, store) => new { usage.StoreId, store.RealName })
  331 + .Select((usage, product, store) => new StoreUsageStatisticsOutput
  332 + {
  333 + StoreId = usage.StoreId,
  334 + StoreName = store.RealName,
  335 + TotalUsageQuantity = SqlFunc.AggregateSum(usage.UsageQuantity),
  336 + TotalUsageAmount = SqlFunc.AggregateSum(usage.UsageQuantity * product.Price),
  337 + UsageCount = SqlFunc.AggregateCount(usage.Id),
  338 + ProductVarietyCount = SqlFunc.AggregateCount(usage.ProductId)
  339 + })
  340 + .ToListAsync();
  341 +
  342 + return new
  343 + {
  344 + success = true,
  345 + data = data,
  346 + total = data.Count,
  347 + message = "门店使用统计查询成功"
  348 + };
  349 + }
  350 + catch (Exception ex)
  351 + {
  352 + _logger.LogError(ex, "获取门店使用统计失败");
  353 + throw NCCException.Oh($"获取门店使用统计失败:{ex.Message}");
  354 + }
  355 + }
  356 + #endregion
  357 +
  358 + #region 统计时间周期内使用趋势
  359 + /// <summary>
  360 + /// 统计时间周期内使用趋势
  361 + /// </summary>
  362 + /// <param name="input">统计查询输入</param>
  363 + /// <returns>使用趋势统计</returns>
  364 + [HttpPost("GetUsageTrendStatistics")]
  365 + public async Task<dynamic> GetUsageTrendStatisticsAsync([FromBody] LqInventoryUsageStatisticsInput input)
  366 + {
  367 + try
  368 + {
  369 + // 先获取基础数据
  370 + var baseData = await _db.Queryable<LqInventoryUsageEntity>()
  371 + .LeftJoin<LqInventoryEntity>((usage, product) => usage.ProductId == product.Id)
  372 + .Where((usage, product) => usage.UsageTime >= input.StartTime && usage.UsageTime <= input.EndTime)
  373 + .Where((usage, product) => usage.IsEffective == StatusEnum.有效.GetHashCode())
  374 + .WhereIF(!string.IsNullOrWhiteSpace(input.ProductId), (usage, product) => usage.ProductId == input.ProductId)
  375 + .WhereIF(!string.IsNullOrWhiteSpace(input.StoreId), (usage, product) => usage.StoreId == input.StoreId)
  376 + .WhereIF(!string.IsNullOrWhiteSpace(input.ProductCategory), (usage, product) => product.ProductCategory == input.ProductCategory)
  377 + .Select((usage, product) => new
  378 + {
  379 + UsageTime = usage.UsageTime,
  380 + UsageQuantity = usage.UsageQuantity,
  381 + UsageAmount = usage.UsageQuantity * product.Price,
  382 + ProductId = usage.ProductId
  383 + })
  384 + .ToListAsync();
  385 +
  386 + // 根据统计类型分组
  387 + var groupedData = input.StatisticsType switch
  388 + {
  389 + "日" => baseData.GroupBy(x => x.UsageTime.Date)
  390 + .Select(g => new UsageTrendStatisticsOutput
  391 + {
  392 + StatisticsDate = g.Key,
  393 + TotalUsageQuantity = g.Sum(x => x.UsageQuantity),
  394 + TotalUsageAmount = g.Sum(x => x.UsageAmount),
  395 + UsageCount = g.Count(),
  396 + ProductVarietyCount = g.Select(x => x.ProductId).Distinct().Count()
  397 + })
  398 + .OrderBy(x => x.StatisticsDate)
  399 + .ToList(),
  400 + "月" => baseData.GroupBy(x => new { x.UsageTime.Year, x.UsageTime.Month })
  401 + .Select(g => new UsageTrendStatisticsOutput
  402 + {
  403 + StatisticsDate = new DateTime(g.Key.Year, g.Key.Month, 1),
  404 + TotalUsageQuantity = g.Sum(x => x.UsageQuantity),
  405 + TotalUsageAmount = g.Sum(x => x.UsageAmount),
  406 + UsageCount = g.Count(),
  407 + ProductVarietyCount = g.Select(x => x.ProductId).Distinct().Count()
  408 + })
  409 + .OrderBy(x => x.StatisticsDate)
  410 + .ToList(),
  411 + _ => baseData.GroupBy(x => x.UsageTime.Date)
  412 + .Select(g => new UsageTrendStatisticsOutput
  413 + {
  414 + StatisticsDate = g.Key,
  415 + TotalUsageQuantity = g.Sum(x => x.UsageQuantity),
  416 + TotalUsageAmount = g.Sum(x => x.UsageAmount),
  417 + UsageCount = g.Count(),
  418 + ProductVarietyCount = g.Select(x => x.ProductId).Distinct().Count()
  419 + })
  420 + .OrderBy(x => x.StatisticsDate)
  421 + .ToList()
  422 + };
  423 +
  424 + return new
  425 + {
  426 + success = true,
  427 + data = groupedData,
  428 + total = groupedData.Count,
  429 + message = "使用趋势统计查询成功"
  430 + };
  431 + }
  432 + catch (Exception ex)
  433 + {
  434 + _logger.LogError(ex, "获取使用趋势统计失败");
  435 + throw NCCException.Oh($"获取使用趋势统计失败:{ex.Message}");
  436 + }
  437 + }
  438 + #endregion
  439 +
  440 + #region 统计产品使用排行榜
  441 + /// <summary>
  442 + /// 统计产品使用排行榜
  443 + /// </summary>
  444 + /// <param name="input">统计查询输入</param>
  445 + /// <returns>产品使用排行榜</returns>
  446 + [HttpPost("GetProductUsageRanking")]
  447 + public async Task<dynamic> GetProductUsageRankingAsync([FromBody] LqInventoryUsageStatisticsInput input)
  448 + {
  449 + try
  450 + {
  451 + var data = await _db.Queryable<LqInventoryUsageEntity>()
  452 + .LeftJoin<LqInventoryEntity>((usage, product) => usage.ProductId == product.Id)
  453 + .Where((usage, product) => usage.UsageTime >= input.StartTime && usage.UsageTime <= input.EndTime)
  454 + .Where((usage, product) => usage.IsEffective == StatusEnum.有效.GetHashCode())
  455 + .WhereIF(!string.IsNullOrWhiteSpace(input.ProductId), (usage, product) => usage.ProductId == input.ProductId)
  456 + .WhereIF(!string.IsNullOrWhiteSpace(input.StoreId), (usage, product) => usage.StoreId == input.StoreId)
  457 + .WhereIF(!string.IsNullOrWhiteSpace(input.ProductCategory), (usage, product) => product.ProductCategory == input.ProductCategory)
  458 + .GroupBy((usage, product) => new { usage.ProductId, product.ProductName, product.ProductCategory })
  459 + .Select((usage, product) => new ProductUsageRankingOutput
  460 + {
  461 + ProductId = usage.ProductId,
  462 + ProductName = product.ProductName,
  463 + ProductCategory = product.ProductCategory,
  464 + TotalUsageQuantity = SqlFunc.AggregateSum(usage.UsageQuantity),
  465 + TotalUsageAmount = SqlFunc.AggregateSum(usage.UsageQuantity * product.Price),
  466 + UsageCount = SqlFunc.AggregateCount(usage.Id),
  467 + StoreCount = SqlFunc.AggregateCount(usage.StoreId)
  468 + })
  469 + .OrderBy("TotalUsageQuantity desc")
  470 + .Take(input.RankingCount)
  471 + .ToListAsync();
  472 +
  473 + // 添加排名
  474 + for (int i = 0; i < data.Count; i++)
  475 + {
  476 + data[i].Ranking = i + 1;
  477 + }
  478 +
  479 + return new
  480 + {
  481 + success = true,
  482 + data = data,
  483 + total = data.Count,
  484 + message = "产品使用排行榜查询成功"
  485 + };
  486 + }
  487 + catch (Exception ex)
  488 + {
  489 + _logger.LogError(ex, "获取产品使用排行榜失败");
  490 + throw NCCException.Oh($"获取产品使用排行榜失败:{ex.Message}");
  491 + }
  492 + }
  493 + #endregion
  494 +
  495 +
  496 + }
  497 +}
... ...
netcore/src/Modularity/Extend/NCC.Extend/LqKdKdjlbService.cs
... ... @@ -5,6 +5,7 @@ using System.Net.Http;
5 5 using System.Threading.Tasks;
6 6 using Mapster;
7 7 using Microsoft.AspNetCore.Mvc;
  8 +using Microsoft.Extensions.Logging;
8 9 using NCC.ClayObject;
9 10 using NCC.Common.Configuration;
10 11 using NCC.Common.Core.Manager;
... ... @@ -22,6 +23,8 @@ using NCC.Extend.Entitys.Dto.LqKdKdjlb;
22 23 using NCC.Extend.Entitys.Enum;
23 24 using NCC.Extend.Entitys.lq_hytk_hytk;
24 25 using NCC.Extend.Entitys.lq_hytk_mx;
  26 +using NCC.Extend.Entitys.lq_hytk_jksyj;
  27 +using NCC.Extend.Entitys.lq_hytk_kjbsyj;
25 28 using NCC.Extend.Entitys.lq_jinsanjiao_user;
26 29 using NCC.Extend.Entitys.lq_kd_deductinfo;
27 30 using NCC.Extend.Entitys.lq_xh_hyhk;
... ... @@ -40,6 +43,8 @@ using NCC.System.Entitys.Permission;
40 43 using SqlSugar;
41 44 using Yitter.IdGenerator;
42 45 using NCC.Extend.Entitys.lq_package_info;
  46 +using NCC.Extend.Entitys.lq_mdxx;
  47 +using NCC.Extend.Entitys.lq_card_transfer_log;
43 48  
44 49 namespace NCC.Extend.LqKdKdjlb
45 50 {
... ... @@ -58,6 +63,7 @@ namespace NCC.Extend.LqKdKdjlb
58 63 private readonly IUserManager _userManager;
59 64 private readonly WeChatBotService _weChatBotService;
60 65 private readonly LqKdKdjlbStringGenerator _stringGenerator;
  66 + private readonly ILogger<LqKdKdjlbService> _logger;
61 67  
62 68 /// <summary>
63 69 /// 初始化一个<see cref="LqKdKdjlbService"/>类型的新实例
... ... @@ -69,7 +75,8 @@ namespace NCC.Extend.LqKdKdjlb
69 75 ISqlSugarRepository<LqKdPxmxEntity> lqKdPxmxRepository,
70 76 IUserManager userManager,
71 77 WeChatBotService weChatBotService,
72   - LqKdKdjlbStringGenerator stringGenerator
  78 + LqKdKdjlbStringGenerator stringGenerator,
  79 + ILogger<LqKdKdjlbService> logger
73 80 )
74 81 {
75 82 _lqKdKdjlbRepository = lqKdKdjlbRepository;
... ... @@ -80,6 +87,7 @@ namespace NCC.Extend.LqKdKdjlb
80 87 _userManager = userManager;
81 88 _weChatBotService = weChatBotService;
82 89 _stringGenerator = stringGenerator;
  90 + _logger = logger;
83 91 }
84 92  
85 93 #region 获取开单记录表
... ... @@ -210,9 +218,9 @@ namespace NCC.Extend.LqKdKdjlb
210 218 .WhereIF(queryKdrq != null, p => p.Kdrq <= new DateTime(endKdrq.ToDate().Year, endKdrq.ToDate().Month, endKdrq.ToDate().Day, 23, 59, 59))
211 219 .WhereIF(!string.IsNullOrEmpty(input.gjlx), p => p.Gjlx.Equals(input.gjlx))
212 220 .WhereIF(!string.IsNullOrEmpty(input.hgjg), p => p.Hgjg.Equals(input.hgjg))
213   - .WhereIF(!string.IsNullOrEmpty(input.zdyj), p => p.Zdyj.Equals(input.zdyj))
214   - .WhereIF(!string.IsNullOrEmpty(input.sfyj), p => p.Sfyj.Equals(input.sfyj))
215   - .WhereIF(!string.IsNullOrEmpty(input.qk), p => p.Qk.Equals(input.qk))
  221 + .WhereIF(input.zdyj != null, p => p.Zdyj > input.zdyj)
  222 + .WhereIF(input.sfyj != null, p => p.Sfyj > input.sfyj)
  223 + .WhereIF(input.qk != null, p => p.Qk > input.qk)
216 224 .WhereIF(!string.IsNullOrEmpty(input.ckfs), p => p.Ckfs.Equals(input.ckfs))
217 225 .WhereIF(!string.IsNullOrEmpty(input.fkfs), p => p.Fkfs.Equals(input.fkfs))
218 226 .WhereIF(!string.IsNullOrEmpty(input.fkyy), p => p.Fkyy.Equals(input.fkyy))
... ... @@ -227,6 +235,7 @@ namespace NCC.Extend.LqKdKdjlb
227 235 .WhereIF(!string.IsNullOrEmpty(input.kdhysjh), p => p.Kdhysjh.Contains(input.kdhysjh))
228 236 .WhereIF(!string.IsNullOrEmpty(input.F_FIleUrl), p => p.F_FIleUrl.Contains(input.F_FIleUrl))
229 237 .WhereIF(!string.IsNullOrEmpty(input.CreateUser), p => p.CreateUser.Equals(input.CreateUser))
  238 + .WhereIF(input.isEffective != 0, p => p.IsEffective == input.isEffective)
230 239 .Select(it => new LqKdKdjlbListOutput
231 240 {
232 241 id = it.Id,
... ... @@ -775,9 +784,9 @@ namespace NCC.Extend.LqKdKdjlb
775 784 .WhereIF(queryKdrq != null, p => p.Kdrq <= new DateTime(endKdrq.ToDate().Year, endKdrq.ToDate().Month, endKdrq.ToDate().Day, 23, 59, 59))
776 785 .WhereIF(!string.IsNullOrEmpty(input.gjlx), p => p.Gjlx.Equals(input.gjlx))
777 786 .WhereIF(!string.IsNullOrEmpty(input.hgjg), p => p.Hgjg.Equals(input.hgjg))
778   - .WhereIF(!string.IsNullOrEmpty(input.zdyj), p => p.Zdyj.Equals(input.zdyj))
779   - .WhereIF(!string.IsNullOrEmpty(input.sfyj), p => p.Sfyj.Equals(input.sfyj))
780   - .WhereIF(!string.IsNullOrEmpty(input.qk), p => p.Qk.Equals(input.qk))
  787 + .WhereIF(input.zdyj != null, p => p.Zdyj > input.zdyj)
  788 + .WhereIF(input.sfyj != null, p => p.Sfyj > input.sfyj)
  789 + .WhereIF(input.qk != null, p => p.Qk > input.qk)
781 790 .WhereIF(!string.IsNullOrEmpty(input.ckfs), p => p.Ckfs.Equals(input.ckfs))
782 791 .WhereIF(!string.IsNullOrEmpty(input.fkfs), p => p.Fkfs.Equals(input.fkfs))
783 792 .WhereIF(!string.IsNullOrEmpty(input.fkyy), p => p.Fkyy.Equals(input.fkyy))
... ... @@ -791,6 +800,7 @@ namespace NCC.Extend.LqKdKdjlb
791 800 .WhereIF(!string.IsNullOrEmpty(input.kdhyc), p => p.Kdhyc.Contains(input.kdhyc))
792 801 .WhereIF(!string.IsNullOrEmpty(input.kdhysjh), p => p.Kdhysjh.Contains(input.kdhysjh))
793 802 .WhereIF(!string.IsNullOrEmpty(input.F_FIleUrl), p => p.F_FIleUrl.Contains(input.F_FIleUrl))
  803 + .WhereIF(input.isEffective != 0, p => p.IsEffective == input.isEffective)
794 804 .Select(it => new LqKdKdjlbListOutput
795 805 {
796 806 id = it.Id,
... ... @@ -2310,6 +2320,396 @@ namespace NCC.Extend.LqKdKdjlb
2310 2320 }
2311 2321 #endregion
2312 2322  
  2323 + #region 会员转卡操作
  2324 + /// <summary>
  2325 + /// 会员转卡操作
  2326 + /// </summary>
  2327 + /// <remarks>
  2328 + /// 转卡是指一个会员把自己剩余的某些品项,转给另外一个会员
  2329 + /// 转卡会员转出的品项,就做退卡操作
  2330 + /// 被转卡会员收到的品项,做开卡操作
  2331 + /// 系统会自动从原开单记录中获取健康师和科技部老师的业绩数据
  2332 + ///
  2333 + /// 示例请求:
  2334 + /// ```json
  2335 + /// {
  2336 + /// "fromMemberId": "member001",
  2337 + /// "toMemberId": "member002",
  2338 + /// "storeId": "store001",
  2339 + /// "signatureFile": "base64签名数据",
  2340 + /// "remarks": "转卡备注信息",
  2341 + /// "transferItems": [
  2342 + /// {
  2343 + /// "billingItemId": "pxmx001",
  2344 + /// "transferQuantity": 5,
  2345 + /// "itemName": "美容项目A",
  2346 + /// "itemPrice": 100.00
  2347 + /// }
  2348 + /// ]
  2349 + /// }
  2350 + /// ```
  2351 + ///
  2352 + /// 参数说明:
  2353 + /// - fromMemberId: 转出会员ID(必填)
  2354 + /// - toMemberId: 转入会员ID(必填)
  2355 + /// - storeId: 门店ID(必填)
  2356 + /// - signatureFile: 转出会员签名文件(必填)
  2357 + /// - remarks: 转卡备注信息(可选)
  2358 + /// - transferItems: 转出品项列表(必填)
  2359 + /// - billingItemId: 开单品项明细ID(必填)
  2360 + /// - transferQuantity: 转出数量(必填,大于0)
  2361 + /// - itemName: 品项名称(必填)
  2362 + /// - itemPrice: 品项价格(必填,大于等于0)
  2363 + ///
  2364 + /// 业务规则:
  2365 + /// - 转出和转入会员必须存在且有效
  2366 + /// - 转出品项的剩余数量必须足够
  2367 + /// - 系统会自动从原开单记录中获取健康师和科技部老师业绩数据
  2368 + /// - 转卡操作会同时创建退卡记录和开卡记录
  2369 + /// - 所有操作在事务中执行,确保数据一致性
  2370 + /// </remarks>
  2371 + /// <param name="input">转卡输入参数</param>
  2372 + /// <returns>转卡结果</returns>
  2373 + /// <response code="200">转卡成功</response>
  2374 + /// <response code="400">参数错误或业务规则验证失败</response>
  2375 + /// <response code="500">服务器错误</response>
  2376 + [HttpPost("TransferCard")]
  2377 + public async Task<TransferCardOutput> TransferCard([FromBody] TransferCardInput input)
  2378 + {
  2379 + if (input == null)
  2380 + {
  2381 + throw NCCException.Oh("转卡参数不能为空");
  2382 + }
  2383 + var userInfo = await _userManager.GetUserInfo();
  2384 + var transferTime = DateTime.Now;
  2385 + try
  2386 + {
  2387 + // 开启事务
  2388 + _db.BeginTran();
  2389 + // 1. 验证转出和转入会员是否存在
  2390 + var fromMember = await _db.Queryable<LqKhxxEntity>().Where(x => x.Id == input.FromMemberId && x.IsEffective == StatusEnum.有效.GetHashCode()).FirstAsync();
  2391 + if (fromMember == null)
  2392 + {
  2393 + throw NCCException.Oh("转出会员不存在或已失效");
  2394 + }
  2395 + var toMember = await _db.Queryable<LqKhxxEntity>().Where(x => x.Id == input.ToMemberId && x.IsEffective == StatusEnum.有效.GetHashCode()).FirstAsync();
  2396 + if (toMember == null)
  2397 + {
  2398 + throw NCCException.Oh("转入会员不存在或已失效");
  2399 + }
  2400 + // 2. 验证转出品项的余额是否足够
  2401 + foreach (var item in input.TransferItems)
  2402 + {
  2403 + var billingItem = await _db.Queryable<LqKdPxmxEntity>().Where(x => x.Id == item.BillingItemId && x.IsEffective == StatusEnum.有效.GetHashCode()).FirstAsync();
  2404 + if (billingItem == null)
  2405 + {
  2406 + throw NCCException.Oh($"品项明细不存在:{item.ItemName}");
  2407 + }
  2408 + // 查询剩余数量
  2409 + var remainingCount = await GetItemRemainingCount(item.BillingItemId);
  2410 + if (remainingCount < item.TransferQuantity)
  2411 + {
  2412 + throw NCCException.Oh($"品项 {item.ItemName} 剩余数量不足,当前剩余:{remainingCount},需要转出:{item.TransferQuantity}");
  2413 + }
  2414 + }
  2415 +
  2416 + // 3. 创建退卡记录(转出方)
  2417 + var refundId = YitIdHelper.NextId().ToString();
  2418 + var totalRefundAmount = input.TransferItems.Sum(x => x.ItemPrice * x.TransferQuantity);
  2419 + var StoreEntity = await _db.Queryable<LqMdxxEntity>().Where(p => p.Id == input.StoreId).FirstAsync();
  2420 + var refundEntity = new LqHytkHytkEntity
  2421 + {
  2422 + Id = refundId,
  2423 + F_CreateTime = transferTime,
  2424 + F_CreateUser = userInfo.userId,
  2425 + IsEffective = StatusEnum.有效.GetHashCode(),
  2426 + Czry = userInfo.userId,
  2427 + Hy = input.FromMemberId,
  2428 + Hymc = fromMember.Khmc,
  2429 + Md = input.StoreId,
  2430 + Mdmc = StoreEntity.Dm,
  2431 + Mdbh = StoreEntity.Mdbm,
  2432 + SignatureFile = input.SignatureFile,
  2433 + Hyzh = input.FromMemberId,
  2434 + Gklx = fromMember.Khlx,
  2435 + Tksj = DateTime.Now,
  2436 + Tkje = totalRefundAmount,
  2437 + ActualRefundAmount = totalRefundAmount, // 转卡时实退金额等于退卡总金额
  2438 + Tkyy = "转卡",
  2439 + Bz = $"转卡给会员:{toMember.Khmc},{input.Remarks}"
  2440 + };
  2441 + await _db.Insertable(refundEntity).ExecuteCommandAsync();
  2442 +
  2443 + // 4. 创建退卡品项明细和业绩记录
  2444 + var refundMxEntities = new List<LqHytkMxEntity>();
  2445 + var refundJksyjEntities = new List<LqHytkJksyjEntity>();
  2446 +
  2447 + var refundKjbsyjEntities = new List<LqHytkKjbsyjEntity>();
  2448 +
  2449 + foreach (var item in input.TransferItems)
  2450 + {
  2451 + var refundPxmxEntity = await _db.Queryable<LqKdPxmxEntity>().Where(p => p.Id == item.BillingItemId).FirstAsync();
  2452 + //计算品项扣除总金额
  2453 + var totalItemDeduction = item.ItemPrice * item.TransferQuantity;
  2454 + //保存退卡明细表
  2455 + var refundMxEntity = new LqHytkMxEntity
  2456 + {
  2457 + Id = YitIdHelper.NextId().ToString(),
  2458 + RefundInfoId = refundId,
  2459 + BillingItemId = item.BillingItemId,
  2460 + CreateTime = transferTime,
  2461 + CreateUser = userInfo.userId,
  2462 + Px = refundPxmxEntity.Px,
  2463 + Pxmc = item.ItemName,
  2464 + Pxjg = item.ItemPrice,
  2465 + Tkje = totalItemDeduction,
  2466 + ProjectNumber = item.TransferQuantity,
  2467 + SourceType = refundPxmxEntity.SourceType,
  2468 + TotalPrice = totalItemDeduction,
  2469 + IsEffective = StatusEnum.有效.GetHashCode()
  2470 + };
  2471 + refundMxEntities.Add(refundMxEntity);
  2472 + var refundKdyjEntities = _db.Queryable<LqKdJksyjEntity>().Where(p => p.Kdpxid == item.BillingItemId).ToList();
  2473 + //保存退卡健康师业绩表
  2474 + foreach (var jks in refundKdyjEntities)
  2475 + {
  2476 + //获取健康师当月金三角id
  2477 + var monthString = DateTime.Now.ToString("yyyyMM");
  2478 + var GetMonTeamResult = await _db.Queryable<LqJinsanjiaoUserEntity>().Where(p => p.UserId == jks.Jkszh && p.Month == monthString).ToListAsync();
  2479 + var GetMonTeam = GetMonTeamResult.FirstOrDefault();
  2480 + if (GetMonTeam == null)
  2481 + {
  2482 + throw NCCException.Oh($"健康师 {jks.Jksxm} 在 {monthString} 月份的金三角团队中不存在,请先配置金三角团队信息");
  2483 + }
  2484 + //获取本月
  2485 + refundJksyjEntities.Add(new LqHytkJksyjEntity
  2486 + {
  2487 + Id = YitIdHelper.NextId().ToString(),
  2488 + Gltkbh = refundId,
  2489 + Jks = jks.Jks,
  2490 + Jksxm = jks.Jksxm,
  2491 + Jkszh = jks.Jkszh,
  2492 + Jksyj = (totalItemDeduction / refundKdyjEntities.Count()),
  2493 + Tksj = DateTime.Now,
  2494 + F_jsjid = GetMonTeam.JsjId,
  2495 + F_tkpxid = refundMxEntity.Id,
  2496 + F_tkpxNumber = item.TransferQuantity,
  2497 + F_CreateTime = transferTime,
  2498 + F_CreateUser = userInfo.userId,
  2499 + CardReturn = refundMxEntity.Id,
  2500 + IsEffective = StatusEnum.有效.GetHashCode()
  2501 + });
  2502 + }
  2503 + //查询科技部老师的业绩
  2504 + var TechTeacherEntities = _db.Queryable<LqKdKjbsyjEntity>().Where(p => p.Kdpxid == item.BillingItemId).ToList();
  2505 + // 创建退卡科技部老师业绩记录
  2506 + foreach (var kjbs in TechTeacherEntities)
  2507 + {
  2508 + refundKjbsyjEntities.Add(new LqHytkKjbsyjEntity
  2509 + {
  2510 + Id = YitIdHelper.NextId().ToString(),
  2511 + Gltkbh = refundId,
  2512 + Kjbls = kjbs.Kjbls,
  2513 + Kjblsxm = kjbs.Kjblsxm,
  2514 + Kjblszh = kjbs.Kjblszh,
  2515 + Kjblsyj = (totalItemDeduction / TechTeacherEntities.Count()),
  2516 + Tksj = transferTime,
  2517 + F_tkpxid = refundMxEntity.Id,
  2518 + F_LaborCost = kjbs.LaborCost,
  2519 + F_tkpxNumber = item.TransferQuantity,
  2520 + F_CreateTime = transferTime,
  2521 + F_CreateUser = userInfo.userId,
  2522 + CardReturn = refundMxEntity.Id,
  2523 + IsEffective = StatusEnum.有效.GetHashCode()
  2524 + });
  2525 + }
  2526 + }
  2527 +
  2528 + await _db.Insertable(refundMxEntities).ExecuteCommandAsync();
  2529 + if (refundJksyjEntities.Any())
  2530 + {
  2531 + await _db.Insertable(refundJksyjEntities).ExecuteCommandAsync();
  2532 + }
  2533 + if (refundKjbsyjEntities.Any())
  2534 + {
  2535 + await _db.Insertable(refundKjbsyjEntities).ExecuteCommandAsync();
  2536 + }
  2537 +
  2538 + // 5. 创建开卡记录(转入方)
  2539 + var billingId = YitIdHelper.NextId().ToString();
  2540 + var billingEntity = new LqKdKdjlbEntity
  2541 + {
  2542 + Id = billingId,
  2543 + CreateTime = transferTime,
  2544 + UpdateTime = transferTime,
  2545 + IsEffective = StatusEnum.有效.GetHashCode(),
  2546 + CreateUser = userInfo.userId,
  2547 + Kdhy = input.ToMemberId,
  2548 + Djmd = input.StoreId,
  2549 + Kdrq = DateTime.Now,
  2550 + Gjlx = toMember.Khlx,
  2551 + Fkfs = "转卡",
  2552 + Sfskdd = "否",
  2553 + Zdyj = input.TransferItems.Sum(x => x.ItemPrice * x.TransferQuantity),
  2554 + Sfyj = input.TransferItems.Sum(x => x.ItemPrice * x.TransferQuantity),
  2555 + Bz = $"从会员 {fromMember.Khmc} 转入,{input.Remarks}"
  2556 + };
  2557 + await _db.Insertable(billingEntity).ExecuteCommandAsync();
  2558 + // 6. 创建开单品项明细和业绩记录
  2559 + var billingPxmxEntities = new List<LqKdPxmxEntity>();
  2560 + var billingJksyjEntities = new List<LqKdJksyjEntity>();
  2561 + var billingKjbsyjEntities = new List<LqKdKjbsyjEntity>();
  2562 +
  2563 + foreach (var item in input.TransferItems)
  2564 + {
  2565 + var refundPxmxEntity = await _db.Queryable<LqKdPxmxEntity>().Where(p => p.Id == item.BillingItemId).FirstAsync();
  2566 + var billingPxmxEntity = new LqKdPxmxEntity
  2567 + {
  2568 + Id = YitIdHelper.NextId().ToString(),
  2569 + Glkdbh = billingId,
  2570 + Px = refundPxmxEntity.Px,
  2571 + Pxmc = item.ItemName,
  2572 + Pxjg = item.ItemPrice,
  2573 + MemberId = input.ToMemberId,
  2574 + CreateTIme = transferTime,
  2575 + ProjectNumber = item.TransferQuantity,
  2576 + IsEnabled = StatusEnum.有效.GetHashCode(),
  2577 + SourceType = refundPxmxEntity.SourceType,
  2578 + TotalPrice = item.ItemPrice * item.TransferQuantity,
  2579 + ActualPrice = item.ItemPrice * item.TransferQuantity,
  2580 + IsEffective = StatusEnum.有效.GetHashCode(),
  2581 + Remark = $"从会员 {fromMember.Khmc} 转入"
  2582 + };
  2583 + billingPxmxEntities.Add(billingPxmxEntity);
  2584 +
  2585 + foreach (var jks in refundJksyjEntities)
  2586 + {
  2587 + billingJksyjEntities.Add(new LqKdJksyjEntity
  2588 + {
  2589 + Id = YitIdHelper.NextId().ToString(),
  2590 + Glkdbh = billingId,
  2591 + Jks = jks.Jks,
  2592 + Jksxm = jks.Jksxm,
  2593 + Jkszh = jks.Jkszh,
  2594 + Jksyj = jks.Jksyj.ToString(),
  2595 + Yjsj = transferTime,
  2596 + Jsj_id = jks.F_jsjid,
  2597 + Kdpxid = billingPxmxEntity.Id,
  2598 + IsEffective = StatusEnum.有效.GetHashCode()
  2599 + });
  2600 + }
  2601 +
  2602 + foreach (var kjbs in refundKjbsyjEntities)
  2603 + {
  2604 + billingKjbsyjEntities.Add(new LqKdKjbsyjEntity
  2605 + {
  2606 + Id = YitIdHelper.NextId().ToString(),
  2607 + Glkdbh = billingId,
  2608 + Kjbls = kjbs.Kjbls,
  2609 + Kjblsxm = kjbs.Kjblsxm,
  2610 + Kjblszh = kjbs.Kjblszh,
  2611 + Kjblsyj = kjbs.Kjblsyj.ToString(),
  2612 + Yjsj = transferTime,
  2613 + Kdpxid = billingPxmxEntity.Id,
  2614 + IsEffective = StatusEnum.有效.GetHashCode()
  2615 + });
  2616 + }
  2617 + }
  2618 + //记录转卡日志
  2619 + var transferLogEntity = new LqCardTransferLogEntity
  2620 + {
  2621 + Id = YitIdHelper.NextId().ToString(),
  2622 + RefundCardId = refundId,
  2623 + BillingCardId = billingId,
  2624 + TransferFromMemberId = input.FromMemberId,
  2625 + TransferToMemberId = input.ToMemberId,
  2626 + TransferAmount = input.TransferItems.Sum(x => x.ItemPrice * x.TransferQuantity),
  2627 + TransferTime = transferTime,
  2628 + OperatorId = userInfo.userId,
  2629 + Remarks = input.Remarks,
  2630 + CreateTime = DateTime.Now,
  2631 + IsEffective = StatusEnum.有效.GetHashCode()
  2632 +
  2633 + };
  2634 + await _db.Insertable(transferLogEntity).ExecuteCommandAsync();
  2635 +
  2636 + await _db.Insertable(billingPxmxEntities).ExecuteCommandAsync();
  2637 + if (billingJksyjEntities.Any())
  2638 + {
  2639 + await _db.Insertable(billingJksyjEntities).ExecuteCommandAsync();
  2640 + }
  2641 + if (billingKjbsyjEntities.Any())
  2642 + {
  2643 + await _db.Insertable(billingKjbsyjEntities).ExecuteCommandAsync();
  2644 + }
  2645 + // 提交事务
  2646 + _db.CommitTran();
  2647 +
  2648 + return new TransferCardOutput
  2649 + {
  2650 + Success = true,
  2651 + TransferId = refundId,
  2652 + RefundId = refundId,
  2653 + BillingId = billingId,
  2654 + TotalAmount = input.TransferItems.Sum(x => x.ItemPrice * x.TransferQuantity),
  2655 + TotalQuantity = input.TransferItems.Sum(x => x.TransferQuantity),
  2656 + FromMemberName = fromMember.Khmc,
  2657 + ToMemberName = toMember.Khmc,
  2658 + TransferTime = transferTime,
  2659 + Message = "转卡操作成功"
  2660 + };
  2661 + }
  2662 + catch (Exception ex)
  2663 + {
  2664 + _db.RollbackTran();
  2665 + _logger.LogError(ex, "转卡操作失败:{Message}", ex.Message);
  2666 + throw NCCException.Oh($"转卡操作失败:{ex.Message}");
  2667 + }
  2668 + }
  2669 + #endregion
  2670 +
  2671 + #region 获取品项剩余数量
  2672 + /// <summary>
  2673 + /// 获取品项剩余数量
  2674 + /// </summary>
  2675 + /// <param name="billingItemId">开单品项明细ID</param>
  2676 + /// <returns>剩余数量</returns>
  2677 + private async Task<int> GetItemRemainingCount(string billingItemId)
  2678 + {
  2679 + try
  2680 + {
  2681 + // 查询购买数量
  2682 + var purchasedCount = await _db.Queryable<LqKdPxmxEntity>()
  2683 + .Where(x => x.Id == billingItemId && x.IsEffective == StatusEnum.有效.GetHashCode())
  2684 + .SumAsync(x => x.ProjectNumber);
  2685 +
  2686 + // 查询消费数量
  2687 + var consumedCount = await _db.Queryable<LqXhPxmxEntity>()
  2688 + .Where(x => x.BillingItemId == billingItemId && x.IsEffective == StatusEnum.有效.GetHashCode())
  2689 + .SumAsync(x => x.ProjectNumber);
  2690 +
  2691 + // 查询退卡数量
  2692 + var refundedCount = await _db.Queryable<LqHytkMxEntity>()
  2693 + .Where(x => x.BillingItemId == billingItemId && x.IsEffective == StatusEnum.有效.GetHashCode())
  2694 + .SumAsync(x => x.ProjectNumber);
  2695 +
  2696 + // 查询储扣数量
  2697 + var deductCount = await _db.Queryable<LqKdDeductinfoEntity>()
  2698 + .Where(x => x.DeductId == billingItemId && x.IsEffective == StatusEnum.有效.GetHashCode())
  2699 + .SumAsync(x => x.ProjectNumber) ?? 0;
  2700 +
  2701 + // 计算剩余数量
  2702 + var remainingCount = (int)(purchasedCount - consumedCount - refundedCount - deductCount);
  2703 + return Math.Max(0, remainingCount); // 确保不为负数
  2704 + }
  2705 + catch (Exception ex)
  2706 + {
  2707 + _logger.LogError(ex, "获取品项剩余数量失败,品项ID:{BillingItemId}", billingItemId);
  2708 + throw NCCException.Oh($"获取品项剩余数量失败:{ex.Message}");
  2709 + }
  2710 + }
  2711 + #endregion
  2712 +
2313 2713  
2314 2714 }
2315 2715 }
... ...
netcore/src/Modularity/Extend/NCC.Extend/LqStatisticsService.cs
... ... @@ -2472,7 +2472,7 @@ namespace NCC.Extend.LqStatistics
2472 2472 /// 保存门店总业绩统计数据
2473 2473 /// </summary>
2474 2474 /// <remarks>
2475   - /// 统计门店的总业绩、欠款金额、总单业绩、储扣总金额、品项数量、首开单数量、升单数量
  2475 + /// 统计门店的总业绩、欠款金额、总单业绩、储扣总金额、品项数量、首开单数量、升单数量、退款业绩、退款次数
2476 2476 ///
2477 2477 /// 示例请求:
2478 2478 /// ```json
... ... @@ -2483,6 +2483,17 @@ namespace NCC.Extend.LqStatistics
2483 2483 ///
2484 2484 /// 参数说明:
2485 2485 /// - statisticsMonth: 统计月份,格式为YYYYMM
  2486 + ///
  2487 + /// 统计指标:
  2488 + /// - 总业绩: 开单记录的总业绩金额
  2489 + /// - 欠款金额: 开单记录的欠款总额
  2490 + /// - 总单业绩: 开单记录的实付业绩
  2491 + /// - 储扣总金额: 储扣记录的金额总和
  2492 + /// - 品项数量: 开单品项的总数量
  2493 + /// - 首开单数量: 首次开单的数量
  2494 + /// - 升单数量: 升单的数量
  2495 + /// - 退款业绩: 退款记录的总金额
  2496 + /// - 退款次数: 退款记录的总次数
2486 2497 /// </remarks>
2487 2498 /// <param name="input">统计输入参数</param>
2488 2499 /// <returns>保存结果</returns>
... ... @@ -2515,7 +2526,9 @@ namespace NCC.Extend.LqStatistics
2515 2526 store_data.F_FirstOrderCount,
2516 2527 store_data.F_UpgradeOrderCount,
2517 2528 store_data.F_FirstOrderPerformance,
2518   - store_data.F_UpgradeOrderPerformance
  2529 + store_data.F_UpgradeOrderPerformance,
  2530 + COALESCE(refund_data.F_RefundAmount, 0) as F_RefundAmount,
  2531 + COALESCE(refund_data.F_RefundCount, 0) as F_RefundCount
2519 2532 FROM (
2520 2533 SELECT
2521 2534 kd.djmd as F_StoreId,
... ... @@ -2544,7 +2557,17 @@ namespace NCC.Extend.LqStatistics
2544 2557 WHERE kd.F_IsEffective = 1
2545 2558 AND DATE_FORMAT(kd.kdrq, '%Y%m') = @statisticsMonth
2546 2559 GROUP BY kd.djmd
2547   - ) item_data ON store_data.F_StoreId = item_data.F_StoreId";
  2560 + ) item_data ON store_data.F_StoreId = item_data.F_StoreId
  2561 + LEFT JOIN (
  2562 + SELECT
  2563 + hytk.md as F_StoreId,
  2564 + COALESCE(SUM(hytk.tkje), 0) as F_RefundAmount,
  2565 + COUNT(DISTINCT hytk.F_Id) as F_RefundCount
  2566 + FROM lq_hytk_hytk hytk
  2567 + WHERE hytk.F_IsEffective = 1
  2568 + AND DATE_FORMAT(hytk.tksj, '%Y%m') = @statisticsMonth
  2569 + GROUP BY hytk.md
  2570 + ) refund_data ON store_data.F_StoreId = refund_data.F_StoreId";
2548 2571  
2549 2572 var storePerformanceData = await _db.Ado.SqlQueryAsync<dynamic>(storePerformanceSql, new { statisticsMonth });
2550 2573  
... ... @@ -2563,6 +2586,8 @@ namespace NCC.Extend.LqStatistics
2563 2586 UpgradeOrderCount = Convert.ToInt32(data.F_UpgradeOrderCount ?? 0),
2564 2587 FirstOrderPerformance = Convert.ToDecimal(data.F_FirstOrderPerformance ?? 0),
2565 2588 UpgradeOrderPerformance = Convert.ToDecimal(data.F_UpgradeOrderPerformance ?? 0),
  2589 + RefundAmount = Convert.ToDecimal(data.F_RefundAmount ?? 0),
  2590 + RefundCount = Convert.ToInt32(data.F_RefundCount ?? 0),
2566 2591 CreateTime = DateTime.Now
2567 2592 }).ToList();
2568 2593  
... ... @@ -3302,6 +3327,8 @@ namespace NCC.Extend.LqStatistics
3302 3327 ItemQuantity = it.ItemQuantity,
3303 3328 FirstOrderCount = it.FirstOrderCount,
3304 3329 UpgradeOrderCount = it.UpgradeOrderCount,
  3330 + RefundAmount = it.RefundAmount,
  3331 + RefundCount = it.RefundCount,
3305 3332 CreateTime = it.CreateTime.HasValue ? it.CreateTime.Value : DateTime.Now
3306 3333 }).ToList();
3307 3334  
... ...
netcore/src/Modularity/Extend/NCC.Extend/LqStudyClassService.cs 0 → 100644
  1 +using System;
  2 +using System.Collections.Generic;
  3 +using System.Linq;
  4 +using System.Threading.Tasks;
  5 +using Microsoft.AspNetCore.Mvc;
  6 +using Microsoft.Extensions.Logging;
  7 +using NCC.Common.Core.Manager;
  8 +using NCC.Common.Enum;
  9 +using NCC.Common.Filter;
  10 +using NCC.Dependency;
  11 +using NCC.DynamicApiController;
  12 +using NCC.Extend.Entitys.Dto.LqStudyClass;
  13 +using NCC.Extend.Entitys.lq_study_class;
  14 +using NCC.Extend.Entitys.lq_study_student;
  15 +using NCC.Extend.Entitys.lq_study_record;
  16 +using NCC.Extend.Interfaces.LqStudyClass;
  17 +using NCC.FriendlyException;
  18 +using NCC.System.Entitys.Permission;
  19 +using SqlSugar;
  20 +using Yitter.IdGenerator;
  21 +using NCC.Extend.Entitys.Enum;
  22 +
  23 +namespace NCC.Extend
  24 +{
  25 + /// <summary>
  26 + /// 学习班级服务
  27 + /// </summary>
  28 + [ApiDescriptionSettings(Tag = "绿纤学习班级管理", Name = "LqStudyClass", Order = 200)]
  29 + [Route("api/Extend/LqStudyClass")]
  30 + public class LqStudyClassService : IDynamicApiController, ITransient, ILqStudyClassService
  31 + {
  32 + private readonly IUserManager _userManager;
  33 + private readonly ILogger<LqStudyClassService> _logger;
  34 + private readonly ISqlSugarClient _db;
  35 +
  36 + /// <summary>
  37 + /// 构造函数
  38 + /// </summary>
  39 + /// <param name="userManager">用户管理器</param>
  40 + /// <param name="logger">日志记录器</param>
  41 + /// <param name="db">数据库客户端</param>
  42 + public LqStudyClassService(IUserManager userManager, ILogger<LqStudyClassService> logger, ISqlSugarClient db)
  43 + {
  44 + _userManager = userManager;
  45 + _logger = logger;
  46 + _db = db;
  47 + }
  48 +
  49 + #region 创建学习班级并添加学员
  50 + /// <summary>
  51 + /// 创建学习班级并添加学员
  52 + /// </summary>
  53 + /// <param name="input">创建输入</param>
  54 + /// <returns>创建结果</returns>
  55 + [HttpPost("CreateClassWithStudents")]
  56 + public async Task<dynamic> CreateClassWithStudentsAsync([FromBody] LqStudyClassCreateWithStudentsInput input)
  57 + {
  58 + try
  59 + {
  60 + _db.Ado.BeginTran();
  61 +
  62 + // 创建班级
  63 + var classId = YitIdHelper.NextId().ToString();
  64 + var classEntity = new LqStudyClassEntity
  65 + {
  66 + Id = classId,
  67 + ClassName = input.ClassName,
  68 + TeacherId = input.TeacherId,
  69 + StartTime = input.StartTime,
  70 + EndTime = input.EndTime,
  71 + Remark = input.Remark,
  72 + CreateUser = _userManager.UserId,
  73 + CreateTime = DateTime.Now,
  74 + IsEffective = StatusEnum.有效.GetHashCode()
  75 + };
  76 +
  77 + await _db.Insertable(classEntity).ExecuteCommandAsync();
  78 +
  79 + // 创建学员
  80 + var studentEntities = new List<LqStudyStudentEntity>();
  81 + foreach (var student in input.Students)
  82 + {
  83 + var studentEntity = new LqStudyStudentEntity
  84 + {
  85 + Id = YitIdHelper.NextId().ToString(),
  86 + EmployeeName = student.EmployeeName,
  87 + EmployeePhone = student.EmployeePhone,
  88 + EmployeeId = student.EmployeeId,
  89 + AdmissionTime = student.AdmissionTime,
  90 + ClassId = classId,
  91 + ClassName = input.ClassName,
  92 + HrBelong = student.HrBelong,
  93 + CreateUser = _userManager.UserId,
  94 + CreateTime = DateTime.Now,
  95 + IsEffective = StatusEnum.有效.GetHashCode()
  96 + };
  97 + studentEntities.Add(studentEntity);
  98 + }
  99 +
  100 + if (studentEntities.Any())
  101 + {
  102 + await _db.Insertable(studentEntities).ExecuteCommandAsync();
  103 + }
  104 +
  105 + _db.Ado.CommitTran();
  106 +
  107 + return new
  108 + {
  109 + success = true,
  110 + data = new
  111 + {
  112 + classId = classId,
  113 + className = input.ClassName,
  114 + studentCount = studentEntities.Count,
  115 + message = $"成功创建班级'{input.ClassName}'并添加{studentEntities.Count}名学员"
  116 + },
  117 + message = "创建成功"
  118 + };
  119 + }
  120 + catch (Exception ex)
  121 + {
  122 + _db.Ado.RollbackTran();
  123 + _logger.LogError(ex, "创建学习班级并添加学员失败");
  124 + throw NCCException.Oh($"创建失败:{ex.Message}");
  125 + }
  126 + }
  127 +
  128 + #endregion
  129 +
  130 + #region 向现有班级添加学员
  131 + /// <summary>
  132 + /// 向现有班级添加学员
  133 + /// </summary>
  134 + /// <param name="input">添加学员输入</param>
  135 + /// <returns>添加结果</returns>
  136 + [HttpPost("AddStudentsToClass")]
  137 + public async Task<dynamic> AddStudentsToClassAsync([FromBody] LqStudyClassAddStudentsInput input)
  138 + {
  139 + try
  140 + {
  141 + // 验证班级是否存在
  142 + var classInfo = await _db.Queryable<LqStudyClassEntity>()
  143 + .Where(x => x.Id == input.ClassId && x.IsEffective == StatusEnum.有效.GetHashCode())
  144 + .FirstAsync();
  145 +
  146 + if (classInfo == null)
  147 + {
  148 + throw NCCException.Oh("班级不存在或已失效");
  149 + }
  150 +
  151 + _db.Ado.BeginTran();
  152 +
  153 + // 创建学员
  154 + var studentEntities = new List<LqStudyStudentEntity>();
  155 + foreach (var student in input.Students)
  156 + {
  157 + var studentEntity = new LqStudyStudentEntity
  158 + {
  159 + Id = YitIdHelper.NextId().ToString(),
  160 + EmployeeName = student.EmployeeName,
  161 + EmployeePhone = student.EmployeePhone,
  162 + EmployeeId = student.EmployeeId,
  163 + AdmissionTime = student.AdmissionTime,
  164 + ClassId = input.ClassId,
  165 + ClassName = classInfo.ClassName,
  166 + HrBelong = student.HrBelong,
  167 + CreateUser = _userManager.UserId,
  168 + CreateTime = DateTime.Now,
  169 + IsEffective = StatusEnum.有效.GetHashCode()
  170 + };
  171 + studentEntities.Add(studentEntity);
  172 + }
  173 +
  174 + if (studentEntities.Any())
  175 + {
  176 + await _db.Insertable(studentEntities).ExecuteCommandAsync();
  177 + }
  178 +
  179 + _db.Ado.CommitTran();
  180 +
  181 + return new
  182 + {
  183 + classId = input.ClassId,
  184 + className = classInfo.ClassName,
  185 + addedStudentCount = studentEntities.Count,
  186 + message = $"成功向班级'{classInfo.ClassName}'添加{studentEntities.Count}名学员"
  187 + };
  188 + }
  189 + catch (Exception ex)
  190 + {
  191 + _db.Ado.RollbackTran();
  192 + _logger.LogError(ex, "向班级添加学员失败");
  193 + throw NCCException.Oh($"添加失败:{ex.Message}");
  194 + }
  195 + }
  196 + #endregion
  197 +
  198 + #region 获取所有班级列表
  199 + /// <summary>
  200 + /// 获取所有班级列表
  201 + /// </summary>
  202 + /// <param name="input">查询输入</param>
  203 + /// <returns>班级列表</returns>
  204 + [HttpGet("GetClassList")]
  205 + public async Task<dynamic> GetClassListAsync([FromQuery] LqStudyClassListQueryInput input)
  206 + {
  207 + try
  208 + {
  209 + var sidx = input.sidx == null ? "id" : input.sidx;
  210 +
  211 + // 查询班级信息
  212 + var data = await _db.Queryable<LqStudyClassEntity>()
  213 + .WhereIF(!string.IsNullOrWhiteSpace(input.ClassName), x => x.ClassName.Contains(input.ClassName))
  214 + .WhereIF(!string.IsNullOrWhiteSpace(input.TeacherId), x => x.TeacherId == input.TeacherId)
  215 + .WhereIF(input.StartTime.HasValue, x => x.StartTime >= input.StartTime.Value)
  216 + .WhereIF(input.EndTime.HasValue, x => x.StartTime <= input.EndTime.Value)
  217 + .WhereIF(input.IsEffective.HasValue, x => x.IsEffective == input.IsEffective.Value)
  218 + .Select(x => new LqStudyClassListOutput
  219 + {
  220 + id = x.Id,
  221 + className = x.ClassName,
  222 + teacherId = x.TeacherId,
  223 + teacherName = SqlFunc.Subqueryable<UserEntity>().Where(u => u.Id == x.TeacherId).Select(u => u.RealName),
  224 + startTime = x.StartTime,
  225 + endTime = x.EndTime,
  226 + remark = x.Remark,
  227 + })
  228 + .MergeTable()
  229 + .OrderBy(sidx + " " + input.sort)
  230 + .ToPagedListAsync(input.currentPage, input.pageSize);
  231 + return PageResult<LqStudyClassListOutput>.SqlSugarPageResult(data);
  232 + }
  233 + catch (Exception ex)
  234 + {
  235 + _logger.LogError(ex, "获取班级列表失败");
  236 + throw NCCException.Oh($"获取班级列表失败:{ex.Message}");
  237 + }
  238 + }
  239 + #endregion
  240 +
  241 + #region 获取班级下所有学员信息
  242 + /// <summary>
  243 + /// 获取班级下所有学员信息(分页)
  244 + /// </summary>
  245 + /// <param name="input">查询输入</param>
  246 + /// <returns>学员列表</returns>
  247 + [HttpGet("GetStudentListByClassId")]
  248 + public async Task<dynamic> GetStudentListByClassIdAsync([FromQuery] LqStudyStudentListQueryInput input)
  249 + {
  250 + try
  251 + {
  252 + var sidx = input.sidx == null ? "id" : input.sidx;
  253 + // 查询学员信息
  254 + var data = await _db.Queryable<LqStudyStudentEntity>()
  255 + .Where(x => x.ClassId == input.ClassId)
  256 + .WhereIF(!string.IsNullOrWhiteSpace(input.EmployeeName), x => x.EmployeeName.Contains(input.EmployeeName))
  257 + .WhereIF(!string.IsNullOrWhiteSpace(input.EmployeePhone), x => x.EmployeePhone.Contains(input.EmployeePhone))
  258 + .WhereIF(!string.IsNullOrWhiteSpace(input.EmployeeId), x => x.EmployeeId == input.EmployeeId)
  259 + .WhereIF(!string.IsNullOrWhiteSpace(input.HrBelong), x => x.HrBelong.Contains(input.HrBelong))
  260 + .WhereIF(input.IsEffective.HasValue, x => x.IsEffective == input.IsEffective.Value)
  261 + .Select(x => new LqStudyStudentListOutput
  262 + {
  263 + id = x.Id,
  264 + employeeName = SqlFunc.Subqueryable<UserEntity>().Where(u => u.Id == x.EmployeeId).Select(u => u.RealName),
  265 + employeePhone = SqlFunc.Subqueryable<UserEntity>().Where(u => u.Id == x.EmployeeId).Select(u => u.MobilePhone),
  266 + employeeId = x.EmployeeId,
  267 + admissionTime = x.AdmissionTime,
  268 + classId = x.ClassId,
  269 + className = x.ClassName
  270 + })
  271 + .MergeTable()
  272 + .OrderBy(sidx + " " + input.sort)
  273 + .ToPagedListAsync(input.currentPage, input.pageSize);
  274 + return PageResult<LqStudyStudentListOutput>.SqlSugarPageResult(data);
  275 + }
  276 + catch (Exception ex)
  277 + {
  278 + _logger.LogError(ex, "获取班级学员列表失败");
  279 + throw NCCException.Oh($"获取班级学员列表失败:{ex.Message}");
  280 + }
  281 + }
  282 + #endregion
  283 +
  284 + #region 学习记录管理
  285 + /// <summary>
  286 + /// 添加学习记录
  287 + /// </summary>
  288 + /// <param name="input">学习记录输入</param>
  289 + /// <returns>添加结果</returns>
  290 + [HttpPost("AddStudyRecord")]
  291 + public async Task AddStudyRecordAsync([FromBody] LqStudyRecordCreateInput input)
  292 + {
  293 + // 验证员工是否存在
  294 + var employee = await _db.Queryable<UserEntity>()
  295 + .Where(x => x.Id == input.EmployeeId && x.RealName == input.EmployeeName)
  296 + .FirstAsync();
  297 +
  298 + if (employee == null)
  299 + {
  300 + throw NCCException.Oh("员工不存在,请检查员工ID和姓名是否正确");
  301 + }
  302 +
  303 + // 如果选择下店协助,验证门店信息
  304 + if (input.IsStoreAssist == 1)
  305 + {
  306 + if (string.IsNullOrWhiteSpace(input.StoreId) || string.IsNullOrWhiteSpace(input.StoreName))
  307 + {
  308 + throw NCCException.Oh("选择下店协助时,门店ID和门店名称不能为空");
  309 + }
  310 + }
  311 + // 创建学习记录
  312 + var recordEntity = new LqStudyRecordEntity
  313 + {
  314 + Id = YitIdHelper.NextId().ToString(),
  315 + EmployeeName = input.EmployeeName,
  316 + EmployeeId = input.EmployeeId,
  317 + StudyType = input.StudyType,
  318 + TransportFee = input.TransportFee,
  319 + StudyDate = input.StudyDate,
  320 + DailyStatus = input.DailyStatus,
  321 + Remark = input.Remark,
  322 + IsStoreAssist = input.IsStoreAssist,
  323 + StoreId = input.IsStoreAssist == 1 ? input.StoreId : null,
  324 + StoreName = input.IsStoreAssist == 1 ? input.StoreName : null,
  325 + CreateUser = _userManager.UserId,
  326 + CreateTime = DateTime.Now,
  327 + IsEffective = 1
  328 + };
  329 + var isOk = await _db.Insertable(recordEntity).ExecuteCommandAsync();
  330 + if (!(isOk > 0)) throw NCCException.Oh(ErrorCode.COM1000);
  331 + }
  332 + #endregion
  333 +
  334 + #region 获取学习记录列表
  335 + /// <summary>
  336 + /// 获取学习记录列表
  337 + /// </summary>
  338 + /// <param name="input">查询输入</param>
  339 + /// <returns>学习记录列表</returns>
  340 + [HttpGet("GetStudyRecordList")]
  341 + public async Task<dynamic> GetStudyRecordListAsync([FromQuery] LqStudyRecordListQueryInput input)
  342 + {
  343 + try
  344 + {
  345 + var sidx = input.sidx == null ? "id" : input.sidx;
  346 +
  347 + // 查询学习记录信息
  348 + var data = await _db.Queryable<LqStudyRecordEntity>()
  349 + .WhereIF(!string.IsNullOrWhiteSpace(input.EmployeeName), x => x.EmployeeName.Contains(input.EmployeeName))
  350 + .WhereIF(!string.IsNullOrWhiteSpace(input.EmployeeId), x => x.EmployeeId == input.EmployeeId)
  351 + .WhereIF(!string.IsNullOrWhiteSpace(input.StudyType), x => x.StudyType.Contains(input.StudyType))
  352 + .WhereIF(input.StudyDateStart.HasValue, x => x.StudyDate >= input.StudyDateStart.Value)
  353 + .WhereIF(input.StudyDateEnd.HasValue, x => x.StudyDate <= input.StudyDateEnd.Value)
  354 + .WhereIF(!string.IsNullOrWhiteSpace(input.DailyStatus), x => x.DailyStatus.Contains(input.DailyStatus))
  355 + .WhereIF(input.IsStoreAssist.HasValue, x => x.IsStoreAssist == input.IsStoreAssist.Value)
  356 + .WhereIF(!string.IsNullOrWhiteSpace(input.StoreId), x => x.StoreId == input.StoreId)
  357 + .WhereIF(input.IsEffective.HasValue, x => x.IsEffective == input.IsEffective.Value)
  358 + .Select(x => new LqStudyRecordListOutput
  359 + {
  360 + id = x.Id,
  361 + employeeName = x.EmployeeName,
  362 + employeeId = x.EmployeeId,
  363 + studyType = x.StudyType,
  364 + transportFee = x.TransportFee,
  365 + studyDate = x.StudyDate,
  366 + dailyStatus = x.DailyStatus,
  367 + remark = x.Remark,
  368 + isStoreAssist = x.IsStoreAssist,
  369 + storeId = x.StoreId,
  370 + storeName = x.StoreName,
  371 + createUser = x.CreateUser,
  372 + createUserName = SqlFunc.Subqueryable<UserEntity>().Where(u => u.Id == x.CreateUser).Select(u => u.RealName),
  373 + createTime = x.CreateTime,
  374 + updateUser = x.UpdateUser,
  375 + updateUserName = SqlFunc.Subqueryable<UserEntity>().Where(u => u.Id == x.UpdateUser).Select(u => u.RealName),
  376 + updateTime = x.UpdateTime,
  377 + isEffective = x.IsEffective
  378 + })
  379 + .MergeTable()
  380 + .OrderBy(sidx + " " + input.sort)
  381 + .ToPagedListAsync(input.currentPage, input.pageSize);
  382 + return PageResult<LqStudyRecordListOutput>.SqlSugarPageResult(data);
  383 + }
  384 + catch (Exception ex)
  385 + {
  386 + _logger.LogError(ex, "获取学习记录列表失败");
  387 + throw NCCException.Oh($"获取学习记录列表失败:{ex.Message}");
  388 + }
  389 + }
  390 + #endregion
  391 +
  392 + #region 作废学习记录
  393 + /// <summary>
  394 + /// 作废学习记录
  395 + /// </summary>
  396 + /// <param name="id">学习记录ID</param>
  397 + /// <returns>作废结果</returns>
  398 + [HttpPost("CancelStudyRecord")]
  399 + public async Task CancelStudyRecordAsync([FromBody] string id)
  400 + {
  401 + var record = await _db.Queryable<LqStudyRecordEntity>().Where(x => x.Id == id).FirstAsync();
  402 + if (record == null) throw NCCException.Oh("学习记录不存在");
  403 + record.IsEffective = StatusEnum.无效.GetHashCode();
  404 + record.UpdateTime = DateTime.Now;
  405 + record.UpdateUser = _userManager.UserId;
  406 + var isOk = await _db.Updateable(record).ExecuteCommandAsync();
  407 + if (!(isOk > 0)) throw NCCException.Oh(ErrorCode.COM1000);
  408 + }
  409 + #endregion
  410 + }
  411 +}
... ...
netcore/src/Modularity/Extend/NCC.Extend/LqTkjlbService.cs
... ... @@ -531,7 +531,7 @@ namespace NCC.Extend.LqTkjlb
531 531  
532 532 #region 漏斗统计
533 533 /// <summary>
534   - /// 获取拓客活动漏斗统计数据
  534 + /// 获取拓客活动漏斗统计数据(优化版本)
535 535 /// </summary>
536 536 /// <param name="eventId">活动ID</param>
537 537 /// <returns>漏斗统计数据</returns>
... ... @@ -540,31 +540,49 @@ namespace NCC.Extend.LqTkjlb
540 540 {
541 541 try
542 542 {
  543 + // 优化版本:使用子查询减少JOIN复杂度
543 544 var sql = @"
544 545 SELECT
545 546 md.F_Id as store_id,
546 547 md.dm as store_name,
547   - COUNT(DISTINCT tk.F_Id) as tk_count, -- 拓客数量
548   - COUNT(DISTINCT CASE WHEN yy.F_Id IS NOT NULL THEN tk.F_CustomerPhone END) as yy_count, -- 预约人数(已确认)
549   - COUNT(DISTINCT CASE WHEN xh.F_Id IS NOT NULL THEN tk.F_CustomerPhone END) as hk_count, -- 耗卡人数
550   - COALESCE(SUM(CASE WHEN xh.F_Id IS NOT NULL THEN xh.xfje END), 0) as hk_amount, -- 耗卡金额
551   - ROUND(
552   - COUNT(DISTINCT CASE WHEN yy.F_Id IS NOT NULL THEN tk.F_CustomerPhone END) * 100.0 /
553   - COUNT(DISTINCT tk.F_Id), 2
554   - ) as yy_conversion_rate, -- 预约转化率(预约人数/拓客数量)
555   - ROUND(
556   - COUNT(DISTINCT CASE WHEN xh.F_Id IS NOT NULL THEN tk.F_CustomerPhone END) * 100.0 /
557   - COUNT(DISTINCT CASE WHEN yy.F_Id IS NOT NULL THEN tk.F_CustomerPhone END), 2
558   - ) as hk_conversion_rate -- 耗卡转化率(耗卡人数/预约人数)
559   - FROM lq_tkjlb tk
560   - JOIN lq_mdxx md ON tk.F_StoreId = md.F_Id
561   - LEFT JOIN lq_yyjl yy ON tk.F_MemberId = yy.gk
562   - AND yy.F_Status = '已确认'
563   - LEFT JOIN lq_xh_hyhk xh ON tk.F_MemberId = xh.hy
564   - AND xh.F_IsEffective = 1
565   - WHERE tk.F_EventId = @eventId
566   - GROUP BY md.F_Id, md.dm
567   - ORDER BY tk_count DESC";
  548 + tk_stats.tk_count,
  549 + tk_stats.yaoy_count,
  550 + tk_stats.yy_count,
  551 + tk_stats.hk_count,
  552 + tk_stats.kd_count,
  553 + tk_stats.hk_amount,
  554 + tk_stats.kd_amount,
  555 + CASE
  556 + WHEN tk_stats.tk_count > 0
  557 + THEN ROUND(tk_stats.yy_count * 100.0 / tk_stats.tk_count, 2)
  558 + ELSE 0
  559 + END as yy_conversion_rate,
  560 + CASE
  561 + WHEN tk_stats.yy_count > 0
  562 + THEN ROUND(tk_stats.hk_count * 100.0 / tk_stats.yy_count, 2)
  563 + ELSE 0
  564 + END as hk_conversion_rate
  565 + FROM lq_mdxx md
  566 + LEFT JOIN (
  567 + SELECT
  568 + tk.F_StoreId,
  569 + COUNT(DISTINCT tk.F_Id) as tk_count,
  570 + COUNT(DISTINCT yy.F_Id) as yaoy_count,
  571 + COUNT(DISTINCT yyjl.F_Id) as yy_count,
  572 + COUNT(DISTINCT xh.F_Id) as hk_count,
  573 + COUNT(DISTINCT kd.F_Id) as kd_count,
  574 + COALESCE(SUM(xh.xfje), 0) as hk_amount,
  575 + COALESCE(SUM(kd.sfyj), 0) as kd_amount
  576 + FROM lq_tkjlb tk
  577 + LEFT JOIN lq_yaoyjl yy ON tk.F_MemberId = yy.yykh AND yy.F_StoreId = tk.F_StoreId
  578 + LEFT JOIN lq_yyjl yyjl ON tk.F_MemberId = yyjl.gk AND yyjl.F_Status = '已确认'
  579 + LEFT JOIN lq_xh_hyhk xh ON tk.F_MemberId = xh.hy AND xh.F_IsEffective = 1
  580 + LEFT JOIN lq_kd_kdjlb kd ON tk.F_MemberId = kd.kdhy AND kd.F_IsEffective = 1
  581 + WHERE tk.F_EventId = @eventId
  582 + GROUP BY tk.F_StoreId
  583 + ) tk_stats ON md.F_Id = tk_stats.F_StoreId
  584 + WHERE tk_stats.F_StoreId IS NOT NULL
  585 + ORDER BY tk_stats.tk_count DESC";
568 586  
569 587 var result = await _db.Ado.SqlQueryAsync<dynamic>(sql, new { eventId });
570 588  
... ... @@ -582,7 +600,7 @@ namespace NCC.Extend.LqTkjlb
582 600 }
583 601  
584 602 /// <summary>
585   - /// 获取拓客活动总体漏斗统计
  603 + /// 获取拓客活动总体漏斗统计(优化版本)
586 604 /// </summary>
587 605 /// <param name="eventId">活动ID</param>
588 606 /// <returns>总体漏斗统计数据</returns>
... ... @@ -593,24 +611,39 @@ namespace NCC.Extend.LqTkjlb
593 611 {
594 612 var sql = @"
595 613 SELECT
596   - COUNT(DISTINCT tk.F_Id) as total_tk_count, -- 总拓客数量
597   - COUNT(DISTINCT CASE WHEN yy.F_Id IS NOT NULL THEN tk.F_CustomerPhone END) as total_yy_count, -- 总预约人数
598   - COUNT(DISTINCT CASE WHEN xh.F_Id IS NOT NULL THEN tk.F_CustomerPhone END) as total_hk_count, -- 总耗卡人数
599   - COALESCE(SUM(CASE WHEN xh.F_Id IS NOT NULL THEN xh.xfje END), 0) as total_hk_amount, -- 总耗卡金额
600   - ROUND(
601   - COUNT(DISTINCT CASE WHEN yy.F_Id IS NOT NULL THEN tk.F_CustomerPhone END) * 100.0 /
602   - COUNT(DISTINCT tk.F_Id), 2
603   - ) as overall_yy_conversion_rate, -- 总体预约转化率
604   - ROUND(
605   - COUNT(DISTINCT CASE WHEN xh.F_Id IS NOT NULL THEN tk.F_CustomerPhone END) * 100.0 /
606   - COUNT(DISTINCT CASE WHEN yy.F_Id IS NOT NULL THEN tk.F_CustomerPhone END), 2
607   - ) as overall_hk_conversion_rate -- 总体耗卡转化率
608   - FROM lq_tkjlb tk
609   - LEFT JOIN lq_yyjl yy ON tk.F_MemberId = yy.gk
610   - AND yy.F_Status = '已确认'
611   - LEFT JOIN lq_xh_hyhk xh ON tk.F_MemberId = xh.hy
612   - AND xh.F_IsEffective = 1
613   - WHERE tk.F_EventId = @eventId";
  614 + SUM(tk_count) as total_tk_count,
  615 + SUM(yaoy_count) as total_yaoy_count,
  616 + SUM(yy_count) as total_yy_count,
  617 + SUM(hk_count) as total_hk_count,
  618 + SUM(kd_count) as total_kd_count,
  619 + SUM(hk_amount) as total_hk_amount,
  620 + SUM(kd_amount) as total_kd_amount,
  621 + CASE
  622 + WHEN SUM(tk_count) > 0
  623 + THEN ROUND(SUM(yy_count) * 100.0 / SUM(tk_count), 2)
  624 + ELSE 0
  625 + END as overall_yy_conversion_rate,
  626 + CASE
  627 + WHEN SUM(yy_count) > 0
  628 + THEN ROUND(SUM(hk_count) * 100.0 / SUM(yy_count), 2)
  629 + ELSE 0
  630 + END as overall_hk_conversion_rate
  631 + FROM (
  632 + SELECT
  633 + COUNT(DISTINCT tk.F_Id) as tk_count,
  634 + COUNT(DISTINCT yy.F_Id) as yaoy_count,
  635 + COUNT(DISTINCT yyjl.F_Id) as yy_count,
  636 + COUNT(DISTINCT xh.F_Id) as hk_count,
  637 + COUNT(DISTINCT kd.F_Id) as kd_count,
  638 + COALESCE(SUM(xh.xfje), 0) as hk_amount,
  639 + COALESCE(SUM(kd.sfyj), 0) as kd_amount
  640 + FROM lq_tkjlb tk
  641 + LEFT JOIN lq_yaoyjl yy ON tk.F_MemberId = yy.yykh AND yy.F_StoreId = tk.F_StoreId
  642 + LEFT JOIN lq_yyjl yyjl ON tk.F_MemberId = yyjl.gk AND yyjl.F_Status = '已确认'
  643 + LEFT JOIN lq_xh_hyhk xh ON tk.F_MemberId = xh.hy AND xh.F_IsEffective = 1
  644 + LEFT JOIN lq_kd_kdjlb kd ON tk.F_MemberId = kd.kdhy AND kd.F_IsEffective = 1
  645 + WHERE tk.F_EventId = @eventId
  646 + ) stats";
614 647  
615 648 var result = await _db.Ado.SqlQueryAsync<dynamic>(sql, new { eventId });
616 649  
... ... @@ -626,10 +659,202 @@ namespace NCC.Extend.LqTkjlb
626 659 throw NCCException.Oh("获取总体漏斗统计数据失败:" + ex.Message);
627 660 }
628 661 }
  662 +
  663 + /// <summary>
  664 + /// 获取拓客活动漏斗统计数据(高性能版本 - 分步查询)
  665 + /// </summary>
  666 + /// <param name="eventId">活动ID</param>
  667 + /// <returns>漏斗统计数据</returns>
  668 + [HttpGet("GetFunnelStatisticsFast/{eventId}")]
  669 + public async Task<dynamic> GetFunnelStatisticsFast(string eventId)
  670 + {
  671 + try
  672 + {
  673 + // 第一步:获取拓客基础数据
  674 + var tkSql = @"
  675 + SELECT
  676 + tk.F_StoreId,
  677 + md.dm as store_name,
  678 + COUNT(DISTINCT tk.F_Id) as tk_count
  679 + FROM lq_tkjlb tk
  680 + JOIN lq_mdxx md ON tk.F_StoreId = md.F_Id
  681 + WHERE tk.F_EventId = @eventId
  682 + GROUP BY tk.F_StoreId, md.dm";
  683 +
  684 + var tkData = await _db.Ado.SqlQueryAsync<dynamic>(tkSql, new { eventId });
  685 + var tkDict = tkData.ToDictionary(x => (string)x.F_StoreId, x => x);
  686 +
  687 + // 第二步:获取邀约数据(按会员ID去重)
  688 + var yaoySql = @"
  689 + SELECT
  690 + tk.F_StoreId,
  691 + COUNT(DISTINCT tk.F_MemberId) as yaoy_count
  692 + FROM lq_tkjlb tk
  693 + LEFT JOIN lq_yaoyjl yy ON tk.F_MemberId = yy.yykh AND yy.F_StoreId = tk.F_StoreId
  694 + WHERE tk.F_EventId = @eventId AND yy.F_Id IS NOT NULL
  695 + GROUP BY tk.F_StoreId";
  696 +
  697 + var yaoyData = await _db.Ado.SqlQueryAsync<dynamic>(yaoySql, new { eventId });
  698 + var yaoyDict = yaoyData.ToDictionary(x => (string)x.F_StoreId, x => (int)x.yaoy_count);
  699 +
  700 + // 第三步:获取预约数据(按会员ID去重)
  701 + var yySql = @"
  702 + SELECT
  703 + tk.F_StoreId,
  704 + COUNT(DISTINCT tk.F_MemberId) as yy_count
  705 + FROM lq_tkjlb tk
  706 + LEFT JOIN lq_yyjl yyjl ON tk.F_MemberId = yyjl.gk AND yyjl.F_Status = '已确认'
  707 + WHERE tk.F_EventId = @eventId AND yyjl.F_Id IS NOT NULL
  708 + GROUP BY tk.F_StoreId";
  709 +
  710 + var yyData = await _db.Ado.SqlQueryAsync<dynamic>(yySql, new { eventId });
  711 + var yyDict = yyData.ToDictionary(x => (string)x.F_StoreId, x => (int)x.yy_count);
  712 +
  713 + // 第四步:获取耗卡数据(按会员ID去重,但金额不去重)
  714 + var hkSql = @"
  715 + SELECT
  716 + tk.F_StoreId,
  717 + COUNT(DISTINCT tk.F_MemberId) as hk_count,
  718 + COALESCE(SUM(xh.xfje), 0) as hk_amount
  719 + FROM lq_tkjlb tk
  720 + LEFT JOIN lq_xh_hyhk xh ON tk.F_MemberId = xh.hy AND xh.F_IsEffective = 1
  721 + WHERE tk.F_EventId = @eventId AND xh.F_Id IS NOT NULL
  722 + GROUP BY tk.F_StoreId";
  723 +
  724 + var hkData = await _db.Ado.SqlQueryAsync<dynamic>(hkSql, new { eventId });
  725 + var hkDict = hkData.ToDictionary(x => (string)x.F_StoreId, x => new { count = (int)x.hk_count, amount = (decimal)x.hk_amount });
  726 +
  727 + // 第五步:获取开单数据(按会员ID去重,但金额不去重)
  728 + var kdSql = @"
  729 + SELECT
  730 + tk.F_StoreId,
  731 + COUNT(DISTINCT tk.F_MemberId) as kd_count,
  732 + COALESCE(SUM(kd.sfyj), 0) as kd_amount
  733 + FROM lq_tkjlb tk
  734 + LEFT JOIN lq_kd_kdjlb kd ON tk.F_MemberId = kd.kdhy AND kd.F_IsEffective = 1
  735 + WHERE tk.F_EventId = @eventId AND kd.F_Id IS NOT NULL
  736 + GROUP BY tk.F_StoreId";
  737 +
  738 + var kdData = await _db.Ado.SqlQueryAsync<dynamic>(kdSql, new { eventId });
  739 + var kdDict = kdData.ToDictionary(x => (string)x.F_StoreId, x => new { count = (int)x.kd_count, amount = (decimal)x.kd_amount });
  740 +
  741 + // 合并结果
  742 + var result = tkDict.Values.Select(tk => new
  743 + {
  744 + store_id = tk.F_StoreId,
  745 + store_name = tk.store_name,
  746 + tk_count = (int)tk.tk_count,
  747 + yaoy_count = yaoyDict.ContainsKey(tk.F_StoreId) ? yaoyDict[tk.F_StoreId] : 0,
  748 + yy_count = yyDict.ContainsKey(tk.F_StoreId) ? yyDict[tk.F_StoreId] : 0,
  749 + hk_count = hkDict.ContainsKey(tk.F_StoreId) ? hkDict[tk.F_StoreId].count : 0,
  750 + kd_count = kdDict.ContainsKey(tk.F_StoreId) ? kdDict[tk.F_StoreId].count : 0,
  751 + hk_amount = hkDict.ContainsKey(tk.F_StoreId) ? hkDict[tk.F_StoreId].amount : 0m,
  752 + kd_amount = kdDict.ContainsKey(tk.F_StoreId) ? kdDict[tk.F_StoreId].amount : 0m,
  753 + yy_conversion_rate = (int)tk.tk_count > 0 ? Math.Round((yyDict.ContainsKey(tk.F_StoreId) ? yyDict[tk.F_StoreId] : 0) * 100.0 / (int)tk.tk_count, 2) : 0,
  754 + hk_conversion_rate = (yyDict.ContainsKey(tk.F_StoreId) ? yyDict[tk.F_StoreId] : 0) > 0 ? Math.Round((hkDict.ContainsKey(tk.F_StoreId) ? hkDict[tk.F_StoreId].count : 0) * 100.0 / (yyDict.ContainsKey(tk.F_StoreId) ? yyDict[tk.F_StoreId] : 0), 2) : 0
  755 + }).OrderByDescending(x => x.tk_count).ToList();
  756 +
  757 + return new
  758 + {
  759 + success = true,
  760 + data = result,
  761 + message = "获取漏斗统计数据成功(高性能版本)"
  762 + };
  763 + }
  764 + catch (Exception ex)
  765 + {
  766 + throw NCCException.Oh("获取漏斗统计数据失败:" + ex.Message);
  767 + }
  768 + }
629 769 #endregion
630 770  
631 771 #region 门店顾客详情
632 772 /// <summary>
  773 + /// 生成门店顾客详情查询SQL
  774 + /// </summary>
  775 + /// <param name="isPaged">是否分页</param>
  776 + /// <returns>SQL语句</returns>
  777 + private string GetStoreCustomerDetailsSql(bool isPaged = false)
  778 + {
  779 + var baseSql = @"
  780 + SELECT
  781 + tk.F_Id as tk_id, -- 拓客记录ID
  782 + tk.F_CustomerPhone as customer_phone, -- 顾客手机号
  783 + tk.F_MemberId as member_id, -- 会员ID
  784 + tk.F_CustomerName as customer_name, -- 顾客姓名
  785 + tk.F_CreateTime as tk_time, -- 拓客时间
  786 + -- 邀约信息
  787 + yaoy.F_Id as yaoy_id, -- 邀约ID
  788 + yaoy.F_CreateTime as yaoy_time, -- 邀约时间
  789 + yaoy.F_Status as yaoy_status, -- 邀约状态
  790 + -- 预约信息
  791 + yy.F_Id as yy_id, -- 预约ID
  792 + yy.F_Status as yy_status, -- 预约状态
  793 + yy.F_CreateTime as yy_time, -- 预约时间
  794 + yy.yysj as appointment_time, -- 预约到店时间
  795 + -- 耗卡信息(聚合)
  796 + xh_summary.total_consume_amount, -- 耗卡总金额
  797 + xh_summary.consume_count, -- 耗卡次数
  798 + xh_summary.first_consume_time, -- 首次耗卡时间
  799 + xh_summary.last_consume_time, -- 最后耗卡时间
  800 + -- 开卡信息(聚合)
  801 + kd_summary.total_billing_amount, -- 开卡总金额
  802 + kd_summary.total_debt_amount, -- 总欠款金额
  803 + kd_summary.billing_count, -- 开卡次数
  804 + kd_summary.first_billing_time, -- 首次开卡时间
  805 + kd_summary.last_billing_time, -- 最后开卡时间
  806 + -- 状态描述
  807 + CASE
  808 + WHEN yaoy.F_Id IS NOT NULL THEN '已邀约'
  809 + ELSE '未邀约'
  810 + END as invitation_status, -- 邀约状态描述
  811 + CASE
  812 + WHEN yy.F_Id IS NOT NULL THEN '已预约'
  813 + ELSE '未预约'
  814 + END as appointment_status, -- 预约状态描述
  815 + CASE
  816 + WHEN xh_summary.total_consume_amount > 0 THEN '已耗卡'
  817 + ELSE '未耗卡'
  818 + END as consume_status, -- 耗卡状态描述
  819 + CASE
  820 + WHEN kd_summary.total_billing_amount > 0 THEN '已开卡'
  821 + ELSE '未开卡'
  822 + END as billing_status -- 开卡状态描述
  823 + FROM lq_tkjlb tk
  824 + LEFT JOIN lq_yaoyjl yaoy ON tk.F_MemberId = yaoy.yykh
  825 + AND yaoy.F_StoreId = tk.F_StoreId
  826 + LEFT JOIN lq_yyjl yy ON tk.F_MemberId = yy.gk
  827 + AND yy.F_Status = '已确认'
  828 + LEFT JOIN (
  829 + SELECT
  830 + hy as member_id,
  831 + SUM(xfje) as total_consume_amount,
  832 + COUNT(*) as consume_count,
  833 + MIN(F_CreateTime) as first_consume_time,
  834 + MAX(F_CreateTime) as last_consume_time
  835 + FROM lq_xh_hyhk
  836 + WHERE F_IsEffective = 1
  837 + GROUP BY hy
  838 + ) xh_summary ON tk.F_MemberId = xh_summary.member_id
  839 + LEFT JOIN (
  840 + SELECT
  841 + kdhy as member_id,
  842 + SUM(sfyj) as total_billing_amount,
  843 + SUM(qk) as total_debt_amount,
  844 + COUNT(*) as billing_count,
  845 + MIN(F_CreateTime) as first_billing_time,
  846 + MAX(F_CreateTime) as last_billing_time
  847 + FROM lq_kd_kdjlb
  848 + WHERE F_IsEffective = 1
  849 + GROUP BY kdhy
  850 + ) kd_summary ON tk.F_MemberId = kd_summary.member_id
  851 + WHERE tk.F_EventId = @eventId
  852 + AND tk.F_StoreId = @storeId
  853 + ORDER BY tk.F_CreateTime DESC";
  854 + return isPaged ? baseSql + " LIMIT @offset, @pageSize" : baseSql;
  855 + }
  856 +
  857 + /// <summary>
633 858 /// 获取门店拓客活动顾客详情
634 859 /// </summary>
635 860 /// <param name="eventId">活动ID</param>
... ... @@ -640,37 +865,7 @@ namespace NCC.Extend.LqTkjlb
640 865 {
641 866 try
642 867 {
643   - var sql = @"
644   - SELECT
645   - tk.F_Id as tk_id, -- 拓客记录ID
646   - tk.F_CustomerPhone as customer_phone, -- 顾客手机号
647   - tk.F_MemberId as member_id, -- 会员ID
648   - tk.F_CustomerName as customer_name, -- 顾客姓名
649   - tk.F_CreateTime as tk_time, -- 拓客时间
650   - yy.F_Id as yy_id, -- 预约ID
651   - yy.F_Status as yy_status, -- 预约状态
652   - yy.F_CreateTime as yy_time, -- 预约时间
653   - yy.yysj as appointment_time, -- 预约到店时间
654   - xh.F_Id as xh_id, -- 耗卡ID
655   - xh.F_CreateTime as xh_time, -- 耗卡时间
656   - xh.xfje as consume_amount, -- 耗卡金额
657   - CASE
658   - WHEN yy.F_Id IS NOT NULL THEN '已预约'
659   - ELSE '未预约'
660   - END as appointment_status, -- 预约状态描述
661   - CASE
662   - WHEN xh.F_Id IS NOT NULL THEN '已耗卡'
663   - ELSE '未耗卡'
664   - END as consume_status -- 耗卡状态描述
665   - FROM lq_tkjlb tk
666   - LEFT JOIN lq_yyjl yy ON tk.F_MemberId = yy.gk
667   - AND yy.F_Status = '已确认'
668   - LEFT JOIN lq_xh_hyhk xh ON tk.F_MemberId = xh.hy
669   - AND xh.F_IsEffective = 1
670   - WHERE tk.F_EventId = @eventId
671   - AND tk.F_StoreId = @storeId
672   - ORDER BY tk.F_CreateTime DESC";
673   -
  868 + var sql = GetStoreCustomerDetailsSql(false);
674 869 var result = await _db.Ado.SqlQueryAsync<dynamic>(sql, new { eventId, storeId });
675 870  
676 871 return new
... ... @@ -699,44 +894,12 @@ namespace NCC.Extend.LqTkjlb
699 894 {
700 895 try
701 896 {
702   - var sql = @"
703   - SELECT
704   - tk.F_Id as tk_id, -- 拓客记录ID
705   - tk.F_CustomerPhone as customer_phone, -- 顾客手机号
706   - tk.F_MemberId as member_id, -- 会员ID
707   - tk.F_CustomerName as customer_name, -- 顾客姓名
708   - tk.F_CreateTime as tk_time, -- 拓客时间
709   - yy.F_Id as yy_id, -- 预约ID
710   - yy.F_Status as yy_status, -- 预约状态
711   - yy.F_CreateTime as yy_time, -- 预约时间
712   - yy.yysj as appointment_time, -- 预约到店时间
713   - xh.F_Id as xh_id, -- 耗卡ID
714   - xh.F_CreateTime as xh_time, -- 耗卡时间
715   - xh.xfje as consume_amount, -- 耗卡金额
716   - CASE
717   - WHEN yy.F_Id IS NOT NULL THEN '已预约'
718   - ELSE '未预约'
719   - END as appointment_status, -- 预约状态描述
720   - CASE
721   - WHEN xh.F_Id IS NOT NULL THEN '已耗卡'
722   - ELSE '未耗卡'
723   - END as consume_status -- 耗卡状态描述
724   - FROM lq_tkjlb tk
725   - LEFT JOIN lq_yyjl yy ON tk.F_MemberId = yy.gk
726   - AND yy.F_Status = '已确认'
727   - LEFT JOIN lq_xh_hyhk xh ON tk.F_MemberId = xh.hy
728   - AND xh.F_IsEffective = 1
729   - WHERE tk.F_EventId = @eventId
730   - AND tk.F_StoreId = @storeId
731   - ORDER BY tk.F_CreateTime DESC
732   - LIMIT @offset, @pageSize";
733   -
  897 + var sql = GetStoreCustomerDetailsSql(true);
734 898 var countSql = @"
735 899 SELECT COUNT(*) as total
736 900 FROM lq_tkjlb tk
737 901 WHERE tk.F_EventId = @eventId
738 902 AND tk.F_StoreId = @storeId";
739   -
740 903 var offset = (pageIndex - 1) * pageSize;
741 904 var result = await _db.Ado.SqlQueryAsync<dynamic>(sql, new { eventId, storeId, offset, pageSize });
742 905 var totalResult = await _db.Ado.SqlQueryAsync<dynamic>(countSql, new { eventId, storeId });
... ...
netcore/src/Modularity/Extend/NCC.Extend/LqXhHyhkService.cs
... ... @@ -193,6 +193,7 @@ namespace NCC.Extend.LqXhHyhk
193 193 .WhereIF(queryHksj != null, p => p.Hksj >= new DateTime(startHksj.ToDate().Year, startHksj.ToDate().Month, startHksj.ToDate().Day, 0, 0, 0))
194 194 .WhereIF(queryHksj != null, p => p.Hksj <= new DateTime(endHksj.ToDate().Year, endHksj.ToDate().Month, endHksj.ToDate().Day, 23, 59, 59))
195 195 .WhereIF(!string.IsNullOrEmpty(input.czry), p => p.Czry.Equals(input.czry))
  196 + .WhereIF(input.isEffective != 0, p => p.IsEffective == input.isEffective)
196 197 .Select(it => new LqXhHyhkListOutput
197 198 {
198 199 id = it.Id,
... ...
netcore/src/Modularity/Extend/NCC.Extend/LqXmzlService.cs
... ... @@ -15,6 +15,12 @@ using System.Linq;
15 15 using System.Threading.Tasks;
16 16 using NCC.Extend.Entitys.lq_xmzl;
17 17 using NCC.Extend.Entitys.Dto.LqXmzl;
  18 +using NCC.Extend.Entitys.lq_kd_pxmx;
  19 +using NCC.Extend.Entitys.lq_xh_pxmx;
  20 +using NCC.Extend.Entitys.lq_hytk_mx;
  21 +using NCC.Extend.Entitys.lq_kd_kdjlb;
  22 +using NCC.Extend.Entitys.lq_xh_hyhk;
  23 +using NCC.Extend.Entitys.lq_hytk_hytk;
18 24 using Yitter.IdGenerator;
19 25 using NCC.Common.Helper;
20 26 using NCC.JsonSerialization;
... ... @@ -28,7 +34,7 @@ namespace NCC.Extend.LqXmzl
28 34 /// <summary>
29 35 /// 项目资料服务
30 36 /// </summary>
31   - [ApiDescriptionSettings(Tag = "绿纤项目资料服务", Name = "LqXmzl", Order = 200)]
  37 + [ApiDescriptionSettings(Tag = "绿纤品项资料服务", Name = "LqXmzl", Order = 200)]
32 38 [Route("api/Extend/[controller]")]
33 39 public class LqXmzlService : ILqXmzlService, IDynamicApiController, ITransient
34 40 {
... ... @@ -46,7 +52,7 @@ namespace NCC.Extend.LqXmzl
46 52 _userManager = userManager;
47 53 }
48 54  
49   - #region 获取项目资料
  55 + #region 获取品项资料
50 56  
51 57 /// <summary>
52 58 /// 获取项目资料
... ... @@ -62,9 +68,9 @@ namespace NCC.Extend.LqXmzl
62 68 }
63 69 #endregion
64 70  
65   - #region 获取项目资料列表
  71 + #region 获取品项资料列表
66 72 /// <summary>
67   - /// 获取项目资料列表
  73 + /// 获取品项资料列表
68 74 /// </summary>
69 75 /// <param name="input">请求参数</param>
70 76 /// <returns></returns>
... ... @@ -114,9 +120,9 @@ namespace NCC.Extend.LqXmzl
114 120 }
115 121 #endregion
116 122  
117   - #region 新建项目资料
  123 + #region 新建品项资料
118 124 /// <summary>
119   - /// 新建项目资料
  125 + /// 新建品项资料
120 126 /// </summary>
121 127 /// <param name="input">参数</param>
122 128 /// <returns></returns>
... ... @@ -131,9 +137,9 @@ namespace NCC.Extend.LqXmzl
131 137 }
132 138 #endregion
133 139  
134   - #region 获取项目资料无分页列表
  140 + #region 获取品项资料无分页列表
135 141 /// <summary>
136   - /// 获取项目资料无分页列表
  142 + /// 获取品项资料无分页列表
137 143 /// </summary>
138 144 /// <param name="input">请求参数</param>
139 145 /// <returns></returns>
... ... @@ -177,9 +183,9 @@ namespace NCC.Extend.LqXmzl
177 183 }
178 184 #endregion
179 185  
180   - #region 导出项目资料
  186 + #region 导出品项资料
181 187 /// <summary>
182   - /// 导出项目资料
  188 + /// 导出品项资料
183 189 /// </summary>
184 190 /// <param name="input">请求参数</param>
185 191 /// <returns></returns>
... ... @@ -225,9 +231,9 @@ namespace NCC.Extend.LqXmzl
225 231 }
226 232 #endregion
227 233  
228   - #region 批量删除项目资料
  234 + #region 批量删除品项资料
229 235 /// <summary>
230   - /// 批量删除项目资料
  236 + /// 批量删除品项资料
231 237 /// </summary>
232 238 /// <param name="ids">主键数组</param>
233 239 /// <returns></returns>
... ... @@ -257,9 +263,9 @@ namespace NCC.Extend.LqXmzl
257 263 }
258 264 #endregion
259 265  
260   - #region 更新项目资料
  266 + #region 更新品项资料
261 267 /// <summary>
262   - /// 更新项目资料
  268 + /// 更新品项资料
263 269 /// </summary>
264 270 /// <param name="id">主键</param>
265 271 /// <param name="input">参数</param>
... ... @@ -273,9 +279,9 @@ namespace NCC.Extend.LqXmzl
273 279 }
274 280 #endregion
275 281  
276   - #region 删除项目资料
  282 + #region 删除品项资料
277 283 /// <summary>
278   - /// 删除项目资料
  284 + /// 删除品项资料
279 285 /// </summary>
280 286 /// <param name="id">主键</param>
281 287 /// <returns></returns>
... ... @@ -292,13 +298,13 @@ namespace NCC.Extend.LqXmzl
292 298 /// </summary>
293 299 /// <param name="fieldName">字段名称,支持:fl1、fl2、fl3、fl4、fl、qt1、beautyType、sourceType</param>
294 300 /// <returns>去重后的字段数据</returns>
295   - [HttpPost("GetDistinctFieldData")]
296   - public async Task<dynamic> GetDistinctFieldData([FromBody] string fieldName)
  301 + [HttpGet("GetDistinctFieldData")]
  302 + public async Task<dynamic> GetDistinctFieldData([FromQuery] string fieldName)
297 303 {
298 304 try
299 305 {
300 306 // 验证字段名称
301   - var validFields = new[] { "fl1", "fl2", "fl3", "fl4", "fl", "qt1", "beautyType", "sourceType" };
  307 + var validFields = new[] { "fl1", "fl2", "fl3", "fl4", "fl", "qt1", "qt2", "beautyType", "sourceType" };
302 308 if (!validFields.Contains(fieldName))
303 309 {
304 310 throw NCCException.Oh($"无效的字段名称: {fieldName}。支持的字段: {string.Join(", ", validFields)}");
... ... @@ -350,6 +356,13 @@ namespace NCC.Extend.LqXmzl
350 356 .Distinct()
351 357 .ToListAsync();
352 358 break;
  359 + case "qt2":
  360 + distinctValues = await _db.Queryable<LqXmzlEntity>()
  361 + .Where(p => !string.IsNullOrEmpty(p.Qt2))
  362 + .Select(p => p.Qt2)
  363 + .Distinct()
  364 + .ToListAsync();
  365 + break;
353 366 case "beautyType":
354 367 distinctValues = await _db.Queryable<LqXmzlEntity>()
355 368 .Where(p => !string.IsNullOrEmpty(p.BeautyType))
... ... @@ -379,6 +392,309 @@ namespace NCC.Extend.LqXmzl
379 392 }
380 393 #endregion
381 394  
  395 + #region 品项维度统计
  396 + /// <summary>
  397 + /// 品项维度统计
  398 + /// </summary>
  399 + /// <remarks>
  400 + /// 按品项维度统计开卡、消耗、退卡等数据
  401 + /// 包括业绩、人数、占比、复购率等指标
  402 + ///
  403 + /// 示例请求:
  404 + /// ```json
  405 + /// {
  406 + /// "startTime": "2024-01-01",
  407 + /// "endTime": "2024-12-31",
  408 + /// "storeId": "store001",
  409 + /// "category": "美容",
  410 + /// "itemId": "item001"
  411 + /// }
  412 + /// ```
  413 + ///
  414 + /// 参数说明:
  415 + /// - startTime: 开始时间(可选)
  416 + /// - endTime: 结束时间(可选)
  417 + /// - storeId: 门店ID(可选)
  418 + /// - category: 品项分类(可选)
  419 + /// - itemId: 品项ID(可选,单个品项统计)
  420 + /// </remarks>
  421 + /// <param name="input">统计输入参数</param>
  422 + /// <returns>品项维度统计数据</returns>
  423 + /// <response code="200">统计成功</response>
  424 + /// <response code="400">参数错误</response>
  425 + /// <response code="500">服务器错误</response>
  426 + [HttpPost("GetItemStatistics")]
  427 + public async Task<dynamic> GetItemStatistics([FromBody] LqXmzlStatisticsInput input)
  428 + {
  429 + try
  430 + {
  431 + // 第一步:获取品项基础信息
  432 + var itemsQuery = _db.Queryable<LqXmzlEntity>()
  433 + .Where(x => x.IsEffective == 1);
  434 +
  435 + if (!string.IsNullOrEmpty(input.ItemId))
  436 + {
  437 + itemsQuery = itemsQuery.Where(x => x.Id == input.ItemId);
  438 + }
  439 +
  440 + if (!string.IsNullOrEmpty(input.Category))
  441 + {
  442 + itemsQuery = itemsQuery.Where(x => x.Fl1 == input.Category || x.Fl2 == input.Category || x.Fl == input.Category);
  443 + }
  444 +
  445 + var items = await itemsQuery.ToListAsync();
  446 +
  447 + if (!items.Any())
  448 + {
  449 + return new
  450 + {
  451 + success = true,
  452 + data = new List<LqXmzlStatisticsOutput>(),
  453 + message = "未找到符合条件的品项"
  454 + };
  455 + }
  456 +
  457 + var itemIds = items.Select(x => x.Id).ToList();
  458 +
  459 + // 第二步:开卡数据统计
  460 + var billingStats = await GetBillingStatistics(itemIds, input);
  461 +
  462 + // 第三步:消耗数据统计
  463 + var consumeStats = await GetConsumeStatistics(itemIds, input);
  464 +
  465 + // 第四步:退卡数据统计
  466 + var refundStats = await GetRefundStatistics(itemIds, input);
  467 +
  468 + // 第五步:计算总数据用于占比计算
  469 + var totalBillingAmount = billingStats.Sum(x => x.BillingAmount);
  470 + var totalConsumeAmount = consumeStats.Sum(x => x.ConsumeAmount);
  471 + var totalBuyers = billingStats.Sum(x => x.TotalBuyers);
  472 +
  473 + // 第六步:合并数据并计算占比
  474 + var result = new List<LqXmzlStatisticsOutput>();
  475 +
  476 + foreach (var item in items)
  477 + {
  478 + var billingData = billingStats.FirstOrDefault(x => x.ItemId == item.Id);
  479 + var consumeData = consumeStats.FirstOrDefault(x => x.ItemId == item.Id);
  480 + var refundData = refundStats.FirstOrDefault(x => x.ItemId == item.Id);
  481 +
  482 + var output = new LqXmzlStatisticsOutput
  483 + {
  484 + ItemId = item.Id,
  485 + ItemName = item.Xmmc,
  486 + ItemNumber = item.Xmbh,
  487 + BillingAmount = billingData?.BillingAmount ?? 0,
  488 + BillingAmountRatio = totalBillingAmount > 0 ? (billingData?.BillingAmount ?? 0) / totalBillingAmount : 0,
  489 + TotalBuyers = billingData?.TotalBuyers ?? 0,
  490 + ItemRatio = totalBuyers > 0 ? (billingData?.TotalBuyers ?? 0) / (decimal)totalBuyers : 0,
  491 + RepeatBuyers = billingData?.RepeatBuyers ?? 0,
  492 + RepeatBuyRate = (billingData?.TotalBuyers ?? 0) > 0 ? (billingData?.RepeatBuyers ?? 0) / (decimal)(billingData?.TotalBuyers ?? 1) : 0,
  493 + ConsumeAmount = consumeData?.ConsumeAmount ?? 0,
  494 + ConsumeAmountRatio = totalConsumeAmount > 0 ? (consumeData?.ConsumeAmount ?? 0) / totalConsumeAmount : 0,
  495 + ConsumePurchaseCount = consumeData?.ConsumePurchaseCount ?? 0,
  496 + ConsumeGiftCount = consumeData?.ConsumeGiftCount ?? 0,
  497 + ConsumeExperienceCount = consumeData?.ConsumeExperienceCount ?? 0,
  498 + RefundAmount = refundData?.RefundAmount ?? 0,
  499 + RefundCount = refundData?.RefundCount ?? 0
  500 + };
  501 +
  502 + result.Add(output);
  503 + }
  504 +
  505 + return new
  506 + {
  507 + success = true,
  508 + data = result,
  509 + message = "品项维度统计成功"
  510 + };
  511 + }
  512 + catch (Exception ex)
  513 + {
  514 + throw NCCException.Oh($"品项维度统计失败:{ex.Message}");
  515 + }
  516 + }
  517 +
  518 + /// <summary>
  519 + /// 获取开卡统计数据
  520 + /// </summary>
  521 + private async Task<List<ItemStatisticsData>> GetBillingStatistics(List<string> itemIds, LqXmzlStatisticsInput input)
  522 + {
  523 + var query = _db.Queryable<LqKdPxmxEntity>()
  524 + .Where(x => itemIds.Contains(x.Px) && x.IsEffective == 1);
  525 +
  526 + // 时间过滤
  527 + if (input.StartTime.HasValue)
  528 + {
  529 + query = query.Where(x => x.CreateTIme >= input.StartTime.Value);
  530 + }
  531 + if (input.EndTime.HasValue)
  532 + {
  533 + query = query.Where(x => x.CreateTIme <= input.EndTime.Value);
  534 + }
  535 +
  536 + // 门店过滤(通过开单记录关联)
  537 + if (!string.IsNullOrEmpty(input.StoreId))
  538 + {
  539 + query = query.InnerJoin<LqKdKdjlbEntity>((px, kd) => px.Glkdbh == kd.Id)
  540 + .Where((px, kd) => kd.Djmd == input.StoreId && kd.IsEffective == 1);
  541 + }
  542 +
  543 + var result = await query
  544 + .GroupBy(x => x.Px)
  545 + .Select(x => new ItemStatisticsData
  546 + {
  547 + ItemId = x.Px,
  548 + BillingAmount = SqlFunc.AggregateSum(x.Pxjg * x.ProjectNumber),
  549 + TotalBuyers = SqlFunc.AggregateCount(x.MemberId),
  550 + RepeatBuyers = 0 // 复购人数需要单独计算
  551 + })
  552 + .ToListAsync();
  553 +
  554 + // 单独计算复购人数
  555 + foreach (var item in result)
  556 + {
  557 + var memberCountQuery = _db.Queryable<LqKdPxmxEntity>()
  558 + .Where(x => x.Px == item.ItemId && x.IsEffective == 1);
  559 +
  560 + if (input.StartTime.HasValue)
  561 + {
  562 + memberCountQuery = memberCountQuery.Where(x => x.CreateTIme >= input.StartTime.Value);
  563 + }
  564 + if (input.EndTime.HasValue)
  565 + {
  566 + memberCountQuery = memberCountQuery.Where(x => x.CreateTIme <= input.EndTime.Value);
  567 + }
  568 +
  569 + if (!string.IsNullOrEmpty(input.StoreId))
  570 + {
  571 + memberCountQuery = memberCountQuery.InnerJoin<LqKdKdjlbEntity>((px, kd) => px.Glkdbh == kd.Id)
  572 + .Where((px, kd) => kd.Djmd == input.StoreId && kd.IsEffective == 1);
  573 + }
  574 +
  575 + var memberStats = await memberCountQuery
  576 + .GroupBy(x => x.MemberId)
  577 + .Having(x => SqlFunc.AggregateCount(x.MemberId) > 1)
  578 + .Select(x => SqlFunc.AggregateCount(x.MemberId))
  579 + .ToListAsync();
  580 +
  581 + item.RepeatBuyers = memberStats.Count;
  582 + }
  583 +
  584 + return result;
  585 + }
  586 +
  587 + /// <summary>
  588 + /// 获取消耗统计数据
  589 + /// </summary>
  590 + private async Task<List<ItemConsumeStatisticsData>> GetConsumeStatistics(List<string> itemIds, LqXmzlStatisticsInput input)
  591 + {
  592 + var query = _db.Queryable<LqXhPxmxEntity>()
  593 + .Where(x => itemIds.Contains(x.Px));
  594 +
  595 + // 时间过滤
  596 + if (input.StartTime.HasValue)
  597 + {
  598 + query = query.Where(x => x.CreateTIme >= input.StartTime.Value);
  599 + }
  600 + if (input.EndTime.HasValue)
  601 + {
  602 + query = query.Where(x => x.CreateTIme <= input.EndTime.Value);
  603 + }
  604 +
  605 + // 门店过滤(通过耗卡记录关联)
  606 + if (!string.IsNullOrEmpty(input.StoreId))
  607 + {
  608 + query = query.InnerJoin<LqXhHyhkEntity>((px, xh) => px.ConsumeInfoId == xh.Id)
  609 + .Where((px, xh) => xh.Md == input.StoreId && xh.IsEffective == 1);
  610 + }
  611 +
  612 + var result = await query
  613 + .GroupBy(x => x.Px)
  614 + .Select(x => new ItemConsumeStatisticsData
  615 + {
  616 + ItemId = x.Px,
  617 + ConsumeAmount = SqlFunc.AggregateSum(x.Pxjg * x.ProjectNumber),
  618 + ConsumePurchaseCount = SqlFunc.AggregateSum(SqlFunc.IIF(x.SourceType == "购买", x.ProjectNumber, 0)),
  619 + ConsumeGiftCount = SqlFunc.AggregateSum(SqlFunc.IIF(x.SourceType == "赠送", x.ProjectNumber, 0)),
  620 + ConsumeExperienceCount = SqlFunc.AggregateSum(SqlFunc.IIF(x.SourceType == "体验", x.ProjectNumber, 0))
  621 + })
  622 + .ToListAsync();
  623 +
  624 + return result;
  625 + }
  626 +
  627 + /// <summary>
  628 + /// 获取退卡统计数据
  629 + /// </summary>
  630 + private async Task<List<ItemRefundStatisticsData>> GetRefundStatistics(List<string> itemIds, LqXmzlStatisticsInput input)
  631 + {
  632 + var query = _db.Queryable<LqHytkMxEntity>()
  633 + .Where(x => itemIds.Contains(x.Px));
  634 +
  635 + // 时间过滤
  636 + if (input.StartTime.HasValue)
  637 + {
  638 + query = query.Where(x => x.Tksj >= input.StartTime.Value);
  639 + }
  640 + if (input.EndTime.HasValue)
  641 + {
  642 + query = query.Where(x => x.Tksj <= input.EndTime.Value);
  643 + }
  644 +
  645 + // 门店过滤(通过退卡记录关联)
  646 + if (!string.IsNullOrEmpty(input.StoreId))
  647 + {
  648 + query = query.InnerJoin<LqHytkHytkEntity>((mx, hytk) => mx.RefundInfoId == hytk.Id)
  649 + .Where((mx, hytk) => hytk.Md == input.StoreId && hytk.IsEffective == 1);
  650 + }
  651 +
  652 + var result = await query
  653 + .GroupBy(x => x.Px)
  654 + .Select(x => new ItemRefundStatisticsData
  655 + {
  656 + ItemId = x.Px,
  657 + RefundAmount = SqlFunc.AggregateSum(x.Tkje ?? 0),
  658 + RefundCount = SqlFunc.AggregateCount(x.Id)
  659 + })
  660 + .ToListAsync();
  661 +
  662 + return result;
  663 + }
  664 + #endregion
  665 +
  666 + }
  667 +
  668 + /// <summary>
  669 + /// 品项统计数据(内部类)
  670 + /// </summary>
  671 + public class ItemStatisticsData
  672 + {
  673 + public string ItemId { get; set; }
  674 + public decimal BillingAmount { get; set; }
  675 + public int TotalBuyers { get; set; }
  676 + public int RepeatBuyers { get; set; }
  677 + }
  678 +
  679 + /// <summary>
  680 + /// 品项消耗统计数据(内部类)
  681 + /// </summary>
  682 + public class ItemConsumeStatisticsData
  683 + {
  684 + public string ItemId { get; set; }
  685 + public decimal ConsumeAmount { get; set; }
  686 + public int ConsumePurchaseCount { get; set; }
  687 + public int ConsumeGiftCount { get; set; }
  688 + public int ConsumeExperienceCount { get; set; }
  689 + }
382 690  
  691 + /// <summary>
  692 + /// 品项退卡统计数据(内部类)
  693 + /// </summary>
  694 + public class ItemRefundStatisticsData
  695 + {
  696 + public string ItemId { get; set; }
  697 + public decimal RefundAmount { get; set; }
  698 + public int RefundCount { get; set; }
383 699 }
384 700 }
... ...
netcore/src/Modularity/Extend/NCC.Extend/LqYcsdDysbmxbService.cs
... ... @@ -28,7 +28,7 @@ namespace NCC.Extend.LqYcsdDysbmxb
28 28 /// <summary>
29 29 /// 当月社保明细表服务
30 30 /// </summary>
31   - [ApiDescriptionSettings(Tag = "Extend",Name = "LqYcsdDysbmxb", Order = 200)]
  31 + [ApiDescriptionSettings(Tag = "Extend", Name = "LqYcsdDysbmxb", Order = 200)]
32 32 [Route("api/Extend/[controller]")]
33 33 public class LqYcsdDysbmxbService : ILqYcsdDysbmxbService, IDynamicApiController, ITransient
34 34 {
... ... @@ -43,7 +43,7 @@ namespace NCC.Extend.LqYcsdDysbmxb
43 43 ISqlSugarRepository<LqYcsdDysbmxbEntity> lqYcsdDysbmxbRepository,
44 44 IUserManager userManager)
45 45 {
46   - _lqYcsdDysbmxbRepository = lqYcsdDysbmxbRepository;
  46 + _lqYcsdDysbmxbRepository = lqYcsdDysbmxbRepository;
47 47 _db = _lqYcsdDysbmxbRepository.Context;
48 48 _userManager = userManager;
49 49 }
... ... @@ -84,23 +84,23 @@ namespace NCC.Extend.LqYcsdDysbmxb
84 84 .WhereIF(!string.IsNullOrEmpty(input.zj), p => p.Zj.Equals(input.zj))
85 85 .WhereIF(!string.IsNullOrEmpty(input.gzk), p => p.Gzk.Equals(input.gzk))
86 86 .WhereIF(!string.IsNullOrEmpty(input.cb), p => p.Cb.Equals(input.cb))
87   - .Select(it=> new LqYcsdDysbmxbListOutput
  87 + .Select(it => new LqYcsdDysbmxbListOutput
88 88 {
89 89 id = it.Id,
90   - xm=it.Xm,
91   - md1=it.Md1,
92   - md2=it.Md2,
93   - gmmd=it.Gmmd,
94   - hxcb=it.Hxcb,
95   - cbyf=it.Cbyf,
96   - yf=it.Yf,
97   - sb=it.Sb,
98   - yb=it.Yb,
99   - zj=it.Zj,
100   - gzk=it.Gzk,
101   - cb=it.Cb,
102   - }).MergeTable().OrderBy(sidx+" "+input.sort).ToPagedListAsync(input.currentPage, input.pageSize);
103   - return PageResult<LqYcsdDysbmxbListOutput>.SqlSugarPageResult(data);
  90 + xm = it.Xm,
  91 + md1 = it.Md1,
  92 + md2 = it.Md2,
  93 + gmmd = it.Gmmd,
  94 + hxcb = it.Hxcb,
  95 + cbyf = it.Cbyf,
  96 + yf = it.Yf,
  97 + sb = it.Sb,
  98 + yb = it.Yb,
  99 + zj = it.Zj,
  100 + gzk = it.Gzk,
  101 + cb = it.Cb,
  102 + }).MergeTable().OrderBy(sidx + " " + input.sort).ToPagedListAsync(input.currentPage, input.pageSize);
  103 + return PageResult<LqYcsdDysbmxbListOutput>.SqlSugarPageResult(data);
104 104 }
105 105  
106 106 /// <summary>
... ... @@ -141,23 +141,23 @@ namespace NCC.Extend.LqYcsdDysbmxb
141 141 .WhereIF(!string.IsNullOrEmpty(input.zj), p => p.Zj.Equals(input.zj))
142 142 .WhereIF(!string.IsNullOrEmpty(input.gzk), p => p.Gzk.Equals(input.gzk))
143 143 .WhereIF(!string.IsNullOrEmpty(input.cb), p => p.Cb.Equals(input.cb))
144   - .Select(it=> new LqYcsdDysbmxbListOutput
  144 + .Select(it => new LqYcsdDysbmxbListOutput
145 145 {
146 146 id = it.Id,
147   - xm=it.Xm,
148   - md1=it.Md1,
149   - md2=it.Md2,
150   - gmmd=it.Gmmd,
151   - hxcb=it.Hxcb,
152   - cbyf=it.Cbyf,
153   - yf=it.Yf,
154   - sb=it.Sb,
155   - yb=it.Yb,
156   - zj=it.Zj,
157   - gzk=it.Gzk,
158   - cb=it.Cb,
159   - }).MergeTable().OrderBy(sidx+" "+input.sort).ToListAsync();
160   - return data;
  147 + xm = it.Xm,
  148 + md1 = it.Md1,
  149 + md2 = it.Md2,
  150 + gmmd = it.Gmmd,
  151 + hxcb = it.Hxcb,
  152 + cbyf = it.Cbyf,
  153 + yf = it.Yf,
  154 + sb = it.Sb,
  155 + yb = it.Yb,
  156 + zj = it.Zj,
  157 + gzk = it.Gzk,
  158 + cb = it.Cb,
  159 + }).MergeTable().OrderBy(sidx + " " + input.sort).ToListAsync();
  160 + return data;
161 161 }
162 162  
163 163 /// <summary>
... ... @@ -179,7 +179,7 @@ namespace NCC.Extend.LqYcsdDysbmxb
179 179 {
180 180 exportData = await this.GetNoPagingList(input);
181 181 }
182   - List<ParamsModel> paramList = "[{\"value\":\"序号\",\"field\":\"id\"},{\"value\":\"姓名\",\"field\":\"xm\"},{\"value\":\"门店1\",\"field\":\"md1\"},{\"value\":\"门店2\",\"field\":\"md2\"},{\"value\":\"购买门店\",\"field\":\"gmmd\"},{\"value\":\"后续参保\",\"field\":\"hxcb\"},{\"value\":\"参保月份\",\"field\":\"cbyf\"},{\"value\":\"月份\",\"field\":\"yf\"},{\"value\":\"社保\",\"field\":\"sb\"},{\"value\":\"医保\",\"field\":\"yb\"},{\"value\":\"总计\",\"field\":\"zj\"},{\"value\":\"工资扣\",\"field\":\"gzk\"},{\"value\":\"成本\",\"field\":\"cb\"},]".ToList<ParamsModel>();
  182 + List<ParamsModel> paramList = "[{\"value\":\"序号\",\"field\":\"id\"},{\"value\":\"姓名\",\"field\":\"xm\"},{\"value\":\"门店1\",\"field\":\"md1\"},{\"value\":\"门店2\",\"field\":\"md2\"},{\"value\":\"购买门店\",\"field\":\"gmmd\"},{\"value\":\"后续参保\",\"field\":\"hxcb\"},{\"value\":\"参保月份\",\"field\":\"cbyf\"},{\"value\":\"月份\",\"field\":\"yf\"},{\"value\":\"社保\",\"field\":\"sb\"},{\"value\":\"医保\",\"field\":\"yb\"},{\"value\":\"总计\",\"field\":\"zj\"},{\"value\":\"工资扣\",\"field\":\"gzk\"},{\"value\":\"成本\",\"field\":\"cb\"},]".ToList<ParamsModel>();
183 183 ExcelConfig excelconfig = new ExcelConfig();
184 184 excelconfig.FileName = "当月社保明细表.xls";
185 185 excelconfig.HeadFont = "微软雅黑";
... ... @@ -222,7 +222,7 @@ namespace NCC.Extend.LqYcsdDysbmxb
222 222 //开启事务
223 223 _db.BeginTran();
224 224 //批量删除当月社保明细表
225   - await _db.Deleteable<LqYcsdDysbmxbEntity>().In(d => d.Id,ids).ExecuteCommandAsync();
  225 + await _db.Deleteable<LqYcsdDysbmxbEntity>().In(d => d.Id, ids).ExecuteCommandAsync();
226 226 //关闭事务
227 227 _db.CommitTran();
228 228 }
... ...