| | |
| | | ElButton: typeof import('element-plus/es')['ElButton'] |
| | | ElCard: typeof import('element-plus/es')['ElCard'] |
| | | ElCheckbox: typeof import('element-plus/es')['ElCheckbox'] |
| | | ElCol: typeof import('element-plus/es')['ElCol'] |
| | | ElConfigProvider: typeof import('element-plus/es')['ElConfigProvider'] |
| | | ElDatePicker: typeof import('element-plus/es')['ElDatePicker'] |
| | | ElDescriptions: typeof import('element-plus/es')['ElDescriptions'] |
| | |
| | | ElRadio: typeof import('element-plus/es')['ElRadio'] |
| | | ElRadioButton: typeof import('element-plus/es')['ElRadioButton'] |
| | | ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup'] |
| | | ElRate: typeof import('element-plus/es')['ElRate'] |
| | | ElRow: typeof import('element-plus/es')['ElRow'] |
| | | ElScrollbar: typeof import('element-plus/es')['ElScrollbar'] |
| | | ElSelect: typeof import('element-plus/es')['ElSelect'] |
| | | ElStep: typeof import('element-plus/es')['ElStep'] |
| | |
| | | ElTabPane: typeof import('element-plus/es')['ElTabPane'] |
| | | ElTabs: typeof import('element-plus/es')['ElTabs'] |
| | | ElTag: typeof import('element-plus/es')['ElTag'] |
| | | ElTooltip: typeof import('element-plus/es')['ElTooltip'] |
| | | ElTreeSelect: typeof import('element-plus/es')['ElTreeSelect'] |
| | | ElUpload: typeof import('element-plus/es')['ElUpload'] |
| | | FileInfoPreview: typeof import('./src/components/fileInfoPreview/index.vue')['default'] |
| | | FilePreview: typeof import('./src/components/filePreview/index.vue')['default'] |
| | |
| | | .rowBtnDiv .normal-btn,.action-btns .normal-btn{ |
| | | padding: 8px 4px !important; |
| | | } |
| | | |
| | | /* Tooltip 宽度与换行控制(Element Plus Teleport 到 body,需要 deep 选择器) */ |
| | | .tooltip-wrap{ |
| | | max-width: 340px !important; |
| | | } |
| | | .tooltip-wrap .el-tooltip__content { |
| | | max-width: 340px !important; |
| | | white-space: normal !important; |
| | | word-break: break-word; |
| | | overflow-wrap: anywhere; |
| | | } |
| | | </style> |
| | |
| | | // 查看个人信息 |
| | | export function queryUserDetail(data: object = {}): ApiPromise { |
| | | return createAxios({ |
| | | baseURL: '/api', |
| | | baseURL: '/api1', |
| | | url: `/admin/common/userDetail`, |
| | | headers: { |
| | | 'Content-Type': 'application/json;charset=UTF-8' |
| | |
| | | const workFlowApi = { |
| | | getWorkFlowParams(data: object = {}) : ApiPromise{ |
| | | return createAxios({ |
| | | baseURL: '/api', |
| | | baseURL: '/api1', |
| | | url: `/approval/templateRelation/relationByType`, |
| | | headers: { |
| | | 'Content-Type': 'application/json;charset=UTF-8' |
| | |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="" class="col-17"> |
| | | <el-select v-model="query.unitProject" placeholder="请选择单位工程" clearable style="width: 100%"> |
| | | <el-option v-for="item in unitProjectOptions" :key="item.value" :label="item.label" :value="item.value" /> |
| | | </el-select> |
| | | <!-- <el-select v-model="query.unitProject" placeholder="请选择单位工程" clearable style="width: 100%">--> |
| | | <!-- <el-option v-for="item in unitProjectOptions" :key="item.value" :label="item.label" :value="item.value" />--> |
| | | <!-- </el-select>--> |
| | | <el-tree-select |
| | | ref="areaIdTreeRef" |
| | | v-model="query.unitProject" |
| | | :data="unitProjectOptions" |
| | | placeholder="请选择单位工程" |
| | | multiple |
| | | collapse-tags |
| | | collapse-tags-tooltip |
| | | clearable |
| | | :default-expand-all="true" |
| | | :render-after-expand="false" |
| | | show-checkbox |
| | | style="width: 170px;" |
| | | @change="importantAreaCh" |
| | | @clear="importantAreaClear" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="交易状态" class="col-30"> |
| | | <el-select v-model="query.status" placeholder="全部" style="width: 100%"> |
| | |
| | | </el-table-column> |
| | | </el-table-column> |
| | | |
| | | <!-- 总价 --> |
| | | <el-table-column label="总价" align="center"> |
| | | <el-table-column label="单价" prop="unitPrice" width="90"> |
| | | <!-- 单价(与“期限(年)”保持相同的父子表头结构) --> |
| | | <el-table-column label="单价" align="center" width="80"> |
| | | <el-table-column label="" prop="unitPrice" width="80"> |
| | | <template #default="{ row }"> |
| | | <div v-if="row.isSpacer" class="spacer-cell"></div> |
| | | <div v-else-if="!row.isMainOrder" class="price-info"> |
| | |
| | | </div> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="数量" prop="quantity" width="50"> |
| | | </el-table-column> |
| | | |
| | | <!-- 数量(与“期限(年)”保持相同的父子表头结构) --> |
| | | <el-table-column label="数量" align="center" width="80"> |
| | | <el-table-column label="" prop="quantity" width="80" align="center"> |
| | | <template #default="{ row }"> |
| | | <div v-if="row.isSpacer" class="spacer-cell"></div> |
| | | <div v-else-if="!row.isMainOrder" class="quantity">{{ row.quantity }}</div> |
| | |
| | | |
| | | <!-- 期限(年) --> |
| | | <el-table-column label="期限(年)" align="center" width="80"> |
| | | <el-table-column label="" prop="period" width="80"> |
| | | <el-table-column label="" prop="period" width="80" align="center"> |
| | | <template #default="{ row }"> |
| | | <div v-if="row.isSpacer" class="spacer-cell"></div> |
| | | <div v-else-if="!row.isMainOrder" class="period-info"> |
| | |
| | | |
| | | const router = useRouter() |
| | | const userStore = useUserInfo() |
| | | const areaIdTreeRef=ref<any>() |
| | | |
| | | // 状态选项(更新为新的工作流程状态) |
| | | const statusOptions = [ |
| | |
| | | const query = reactive({ |
| | | productName: '', |
| | | industry: '', |
| | | unitProject: '', |
| | | unitProject: [] as string[], |
| | | productType: '', |
| | | productSubType: '', |
| | | importantDistrictIdList: [] as string[], |
| | | orderNo: '', |
| | | status: '', |
| | | dateRange: [], |
| | | dateRange: [] as string[], |
| | | }) |
| | | |
| | | // 分页信息 |
| | |
| | | return 'currency' |
| | | } |
| | | |
| | | const importantAreaCh=()=>{ |
| | | let checkedKeys = areaIdTreeRef.value!.getCheckedNodes(false, true) |
| | | if(checkedKeys&&checkedKeys.length>0&& query.unitProject.length>0){ |
| | | query.importantDistrictIdList=[] as string[] |
| | | checkedKeys.forEach((item:any)=>{ |
| | | if(item.children&&item.children.length>0){ |
| | | query.importantDistrictIdList.push(item.value) |
| | | } |
| | | }) |
| | | } |
| | | } |
| | | |
| | | const importantAreaClear=()=>{ |
| | | query.unitProject = [] as string[] |
| | | query.importantDistrictIdList = [] as string[] |
| | | areaIdTreeRef.value.setCheckedKeys([]) |
| | | } |
| | | |
| | | // 获取行业领域选项 |
| | | const getIndustryOptions = async () => { |
| | | try { |
| | |
| | | try { |
| | | const res = await productApi.getCategoryByParent({ parentId: industryCode }) |
| | | if (res?.code === 200 && res.data) { |
| | | unitProjectOptions.value = res.data.map((item: any) => ({ |
| | | label: item.name, |
| | | value: item.id |
| | | })) |
| | | unitProjectOptions.value = handleIndustryData(res.data) |
| | | } |
| | | } catch (error) { |
| | | console.error('获取单位工程选项失败:', error) |
| | | unitProjectOptions.value = [] |
| | | } |
| | | } |
| | | |
| | | const handleIndustryData=(list:any)=>{ |
| | | if(list&& list.length>0){ |
| | | let data=list.map((item:any)=>{ |
| | | return { |
| | | label:item.name, |
| | | value:item.id, |
| | | parentId:item.parentId, |
| | | parentName:item.parentName, |
| | | children:item.childrenList?handleIndustryChildData(item,item.childrenList):[] |
| | | } |
| | | }) |
| | | return data |
| | | } |
| | | } |
| | | const handleIndustryChildData=(parentItem:any,childList:any)=>{ |
| | | if(childList&& childList.length>0){ |
| | | let data=childList.map((item:any)=>{ |
| | | return { |
| | | parentId:parentItem.id, |
| | | parentName:parentItem.name, |
| | | label:item.name, |
| | | value:item.id, |
| | | children:item.childrenList?handleIndustryChildData(item,item.childrenList):[] |
| | | } |
| | | }) |
| | | return data |
| | | } |
| | | } |
| | | |
| | |
| | | // 处理行业领域变化 |
| | | const handleIndustryChange = async (value: string) => { |
| | | // 清空单位工程选择 |
| | | query.unitProject = '' |
| | | query.unitProject = [] as string[] |
| | | // 获取对应的单位工程选项 |
| | | await getUnitProjectOptions(value) |
| | | } |
| | |
| | | |
| | | // 添加产品条件查询 |
| | | if (query.industry) payload.industryId = query.industry |
| | | if (query.unitProject) payload.unitProjectId = query.unitProject |
| | | if (query.unitProject.length > 0) payload.unitProjectId = query.unitProject |
| | | if (query.importantDistrictIdList.length > 0) payload.importantDistrictId = query.importantDistrictIdList |
| | | if (query.productType) payload.productTypeId = query.productType |
| | | if (query.productSubType) payload.productSubTypeId = query.productSubType |
| | | |
| | | // 根据是否有产品条件选择不同的API |
| | | const hasProductConditions = query.industry || query.unitProject || query.productType || query.productSubType |
| | | const hasProductConditions = query.industry || query.unitProject.length > 0 || query.productType || query.productSubType |
| | | const apiMethod = hasProductConditions ? fetchApprovalPageWithProductConditions : fetchApprovalPage |
| | | |
| | | const res = (await apiMethod(payload)) as any |
| | |
| | | Object.assign(query, { |
| | | productName: '', |
| | | industry: '', |
| | | unitProject: '', |
| | | unitProject: [], |
| | | productType: '', |
| | | productSubType: '', |
| | | orderNo: '', |
| | |
| | | .period-info { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | gap: 8px; |
| | | font-size: 12px; |
| | | |
| | |
| | | <el-icon class="section-icon"><Goods /></el-icon> |
| | | <span>产品基本信息</span> |
| | | </div> |
| | | <div class="id-info">产品ID:{{ currentProductId || '未提供' }}</div> |
| | | <!-- <div class="id-info">产品ID:{{ currentProductId || '未提供' }}</div>--> |
| | | </div> |
| | | </template> |
| | | |
| | |
| | | function handleToggleEnableStatus(row: any) { |
| | | const newStatus = row.enableStatus === 'ENABLED' ? 'DISABLED' : 'ENABLED' |
| | | ElMessageBox.confirm( |
| | | `确认要${newStatus === 'ENABLED' ? '启用' : '停用'}该价格(ID: ${row.id})吗?`, |
| | | `确认要${newStatus === 'ENABLED' ? '启用' : '停用'}该定价标准吗?`, |
| | | '状态变更', |
| | | { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' } |
| | | ) |
| | |
| | | <template> |
| | | <el-dialog |
| | | v-model="visible" |
| | | title="产品订单" |
| | | title="产品订购" |
| | | width="900px" |
| | | destroy-on-close |
| | | class="order-status-dialog" |
| | |
| | | <table class="order-info-table"> |
| | | <tbody> |
| | | <tr> |
| | | <td class="label">订单编号:</td> |
| | | <td class="value">{{ order.id }}</td> |
| | | <td class="label">申请时间:</td> |
| | | <td class="label">订单编号</td> |
| | | <td class="value"> |
| | | {{ order.id }} |
| | | <el-link type="primary" @click="goBuyerCenter" style="margin-left: 8px">前往买家中心</el-link> |
| | | </td> |
| | | <td class="label">申请时间</td> |
| | | <td class="value">{{ order.applyTime }}</td> |
| | | </tr> |
| | | <tr> |
| | | <td class="label">产品名称:</td> |
| | | <td class="label">产品名称</td> |
| | | <td class="value">{{ order.productName }}</td> |
| | | <td class="label">提供者:</td> |
| | | <td class="label">提供者</td> |
| | | <td class="value">{{ order.provider }}</td> |
| | | </tr> |
| | | <tr> |
| | | <td class="label">订单状态:</td> |
| | | <td class="label">订单状态</td> |
| | | <td class="value">{{ statusText(order.status) }}</td> |
| | | <td></td> |
| | | <td class="value link"> |
| | |
| | | |
| | | <script setup lang="ts"> |
| | | import { ref, computed, watch } from 'vue' |
| | | import { useRouter } from 'vue-router' |
| | | |
| | | interface Props { |
| | | modelValue: boolean |
| | |
| | | |
| | | const loading = ref(false) |
| | | const order = ref<OrderDetail | null>(null) |
| | | const router = useRouter() |
| | | |
| | | // 模拟订单数据 |
| | | const mockOrders: Record<string, OrderDetail> = { |
| | |
| | | // 仅演示 |
| | | window.alert('这里可跳转到订单详情页(示例)') |
| | | } |
| | | |
| | | const goBuyerCenter = () => { |
| | | router.push({ name: 'tradeBuyerCenter', query: { t: String(Date.now()) } }) |
| | | } |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | |
| | | :colspan="getColspan(priceItem)" |
| | | class="feature-value" |
| | | > |
| | | <div class="order-methods"> |
| | | <span |
| | | v-for="method in priceItem.priceSettings" |
| | | :key="method" |
| | | class="method-item" |
| | | > |
| | | ✓ {{ getPriceSettingText(method) }} |
| | | </span> |
| | | </div> |
| | | {{ priceItem.priceSettings.map((m:any) => getPriceSettingText(m)).join('、') }} |
| | | </td> |
| | | </tr> |
| | | <tr> |
| | |
| | | :colspan="getColspan(priceItem)" |
| | | class="feature-value" |
| | | > |
| | | <div class="price-info"> |
| | | <div |
| | | v-if="priceItem.priceSettings.includes('POINTS') && priceItem.pointsAmount > 0" |
| | | class="price-item" |
| | | > |
| | | <div class="price-lable-icon"> |
| | | <el-icon class="price-icon points"><Coin /></el-icon> |
| | | <span class="price-label">积分</span> |
| | | </div> |
| | | <span class="price-value points">{{ formatNumber(priceItem.pointsAmount) }} / {{ getPriceUnitText(priceItem.priceUnit) }}</span> |
| | | </div> |
| | | <div |
| | | v-if="priceItem.priceSettings.includes('CURRENCY') && priceItem.currencyAmount > 0" |
| | | class="price-item" |
| | | > |
| | | <div class="price-lable-icon"> |
| | | <span class="price-icon currency">¥</span> |
| | | <span class="price-label">货币</span> |
| | | </div> |
| | | <span class="price-value currency">{{ formatNumber(priceItem.currencyAmount) }} / {{ getPriceUnitText(priceItem.priceUnit) }}</span> |
| | | </div> |
| | | <div |
| | | v-if="priceItem.priceSettings.includes('FREE')" |
| | | class="price-item" |
| | | > |
| | | <span class="price-label">费用</span> |
| | | <span class="price-value free">免费</span> |
| | | </div> |
| | | <div |
| | | v-if="priceItem.priceSettings.includes('AGREEMENT')" |
| | | class="price-item" |
| | | > |
| | | <span class="price-label">协议:</span> |
| | | <span class="price-value agreement">每{{ getPriceUnitText(priceItem.priceUnit) }}</span> |
| | | </div> |
| | | </div> |
| | | {{ renderPrice(priceItem) }} |
| | | </td> |
| | | </tr> |
| | | <tr> |
| | |
| | | <table class="order-info-table"> |
| | | <tbody> |
| | | <tr> |
| | | <td class="label">订单编号:</td> |
| | | <td class="value">{{ orderStatus.id }}</td> |
| | | <td class="label">申请时间:</td> |
| | | <td class="label">订单编号</td> |
| | | <td class="value"> |
| | | {{ orderStatus.id }} |
| | | <el-link type="primary" @click="goBuyerCenter" style="margin-left: 8px">点击查看</el-link> |
| | | </td> |
| | | <td class="label">申请时间</td> |
| | | <td class="value">{{ orderStatus.applyTime }}</td> |
| | | </tr> |
| | | <tr> |
| | | <td class="label">产品名称:</td> |
| | | <td class="label">产品名称</td> |
| | | <td class="value">{{ orderStatus.productName }}</td> |
| | | <td class="label">提供者:</td> |
| | | <td class="label">提供者</td> |
| | | <td class="value">{{ orderStatus.provider }}</td> |
| | | </tr> |
| | | <tr> |
| | | <td class="label">订单状态:</td> |
| | | <td class="label">订单状态</td> |
| | | <td class="value">{{ statusText(orderStatus.status) }}</td> |
| | | <td></td> |
| | | <td class="value link"> |
| | |
| | | |
| | | <script setup lang="ts"> |
| | | import { ref, watch, computed, onMounted } from 'vue' |
| | | import { useRouter } from 'vue-router' |
| | | import { ElMessage } from 'element-plus' |
| | | import { useRoute } from 'vue-router' |
| | | import productPricingApi from '@/api/productPricingApi' |
| | |
| | | import workFlowApi from '@/api/workFlowApi' |
| | | |
| | | const route = useRoute() |
| | | const router = useRouter() |
| | | |
| | | interface PriceItem { |
| | | id: number |
| | |
| | | const viewOrder = () => { |
| | | window.alert('这里可跳转到订单详情页(示例)') |
| | | } |
| | | |
| | | const goBuyerCenter = () => { |
| | | router.push({ name: 'tradeBuyerCenter', query: { t: String(Date.now()) } }) |
| | | } |
| | | |
| | | const selectedCount = computed(() => orderSuites.value.filter(s => s.selected).length) |
| | | const totalByType = computed(() => { |
| | |
| | | try { |
| | | await removeFromCart(String(suite.id)) |
| | | orderSuites.value.splice(index, 1) |
| | | selectedSuiteIds.value.delete(suite.id) |
| | | } catch (e) { |
| | | } |
| | | } |
| | |
| | | PRIVATE_INCREMENT: '私有增量包', |
| | | PUBLIC_INCREMENT: '公有增量包', |
| | | OTA: 'OTA服务', |
| | | CLOUD: '云服务' |
| | | CLOUD: '云服务', |
| | | RESOURCE_PACKAGE: '资源包', |
| | | PERSONAL: '个人' |
| | | } |
| | | return map[salesForm] || salesForm |
| | | } |
| | |
| | | return map[unit] || unit |
| | | } |
| | | |
| | | // 统一渲染价格:去除“积分/货币/费用/协议”等类型前缀,仅输出纯价格文本 |
| | | const renderPrice = (priceItem: PriceItem) => { |
| | | const segments: string[] = [] |
| | | if (priceItem.priceSettings.includes('POINTS') && priceItem.pointsAmount > 0) { |
| | | segments.push(`${formatNumber(priceItem.pointsAmount)} / ${getPriceUnitText(priceItem.priceUnit)}`) |
| | | } |
| | | if (priceItem.priceSettings.includes('CURRENCY') && priceItem.currencyAmount > 0) { |
| | | segments.push(`${formatNumber(priceItem.currencyAmount)} / ${getPriceUnitText(priceItem.priceUnit)}`) |
| | | } |
| | | if (priceItem.priceSettings.includes('FREE')) { |
| | | segments.push('免费') |
| | | } |
| | | if (priceItem.priceSettings.includes('AGREEMENT')) { |
| | | segments.push(`每${getPriceUnitText(priceItem.priceUnit)}`) |
| | | } |
| | | return segments.join(';') |
| | | } |
| | | |
| | | // 获取分组后的表头数据 |
| | | const getGroupedHeaders = (tabData: PriceItem[]) => { |
| | | const groups: Record<string, { count: number; productSuite: string }> = {} |
| | |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="" class="col-17"> |
| | | <el-select v-model="query.unitProject" placeholder="请选择单位工程" clearable style="width: 100%"> |
| | | <el-option v-for="item in unitProjectOptions" :key="item.value" :label="item.label" :value="item.value" /> |
| | | </el-select> |
| | | <!-- <el-select v-model="query.unitProject" placeholder="请选择单位工程" clearable style="width: 100%">--> |
| | | <!-- <el-option v-for="item in unitProjectOptions" :key="item.value" :label="item.label" :value="item.value" />--> |
| | | <!-- </el-select>--> |
| | | <el-tree-select |
| | | ref="areaIdTreeRef" |
| | | v-model="query.unitProject" |
| | | :data="unitProjectOptions" |
| | | placeholder="请选择单位工程" |
| | | multiple |
| | | collapse-tags |
| | | collapse-tags-tooltip |
| | | clearable |
| | | :default-expand-all="true" |
| | | :render-after-expand="false" |
| | | show-checkbox |
| | | style="width: 170px;" |
| | | @change="importantAreaCh" |
| | | @clear="importantAreaClear" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="交易状态" class="col-30"> |
| | | <el-select v-model="query.status" placeholder="全部" style="width: 100%"> |
| | |
| | | <!-- 第三行:操作按钮(右对齐) --> |
| | | <div class="form-row actions"> |
| | | <el-form-item class="row-actions"> |
| | | <el-button type="primary" @click="handleSearch" :icon="Search">查询</el-button> |
| | | <el-button @click="reset" :icon="Refresh">重置</el-button> |
| | | <el-button type="primary" @click="handleSearch" icon="Search">查询</el-button> |
| | | <el-button @click="reset" icon="Refresh">重置</el-button> |
| | | </el-form-item> |
| | | </div> |
| | | </el-form> |
| | |
| | | </el-table-column> |
| | | </el-table-column> |
| | | |
| | | <!-- 总价 --> |
| | | <el-table-column label="总价" align="center"> |
| | | <el-table-column label="单价" prop="unitPrice" width="90"> |
| | | <template #default="{ row }"> |
| | | <div v-if="row.isSpacer" class="spacer-cell"></div> |
| | | <div v-else-if="!row.isMainOrder" class="price-info"> |
| | | <span v-if="row.priceType === 'points'" class="price-points"> |
| | | 积分 {{ row.unitPrice }} |
| | | </span> |
| | | <span v-else-if="row.priceType === 'currency'" class="price-currency"> |
| | | 货币 {{ row.unitPrice }} |
| | | </span> |
| | | <span v-else-if="row.priceType === 'agreement'" class="price-agreement"> |
| | | 协议 |
| | | </span> |
| | | <span v-else-if="row.priceType === 'free'" class="price-free"> |
| | | 免费 |
| | | </span> |
| | | </div> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="数量" prop="quantity" width="50"> |
| | | <!-- 数量 --> |
| | | <el-table-column label="数量" align="center" width="80"> |
| | | <el-table-column label="" prop="quantity" width="80" align="center"> |
| | | <template #default="{ row }"> |
| | | <div v-if="row.isSpacer" class="spacer-cell"></div> |
| | | <div v-else-if="!row.isMainOrder" class="quantity">{{ row.quantity }}</div> |
| | |
| | | |
| | | <!-- 期限(年) --> |
| | | <el-table-column label="期限(年)" align="center" width="80"> |
| | | <el-table-column label="" prop="period" width="80"> |
| | | <el-table-column label="" prop="period" width="80" align="center"> |
| | | <template #default="{ row }"> |
| | | <div v-if="row.isSpacer" class="spacer-cell"></div> |
| | | <div v-else-if="!row.isMainOrder" class="period-info"> |
| | |
| | | const router = useRouter() |
| | | const userStore = useUserInfo() |
| | | |
| | | const areaIdTreeRef=ref() |
| | | |
| | | // 状态选项(更新为新的工作流程状态) |
| | | const statusOptions = [ |
| | | { label: '全部', value: '' }, |
| | |
| | | const productSubTypeOptions = ref<any[]>([]) |
| | | |
| | | // 查询条件 |
| | | const query = reactive({ |
| | | type BuyerQuery = { |
| | | productName: string |
| | | industry: string |
| | | unitProject: string[] |
| | | productType: string |
| | | productSubType: string |
| | | importantDistrictIdList: string[] |
| | | orderNo: string |
| | | status: string |
| | | dateRange: string[] |
| | | } |
| | | |
| | | const query = reactive<BuyerQuery>({ |
| | | productName: '', |
| | | industry: '', |
| | | unitProject: '', |
| | | unitProject: [], |
| | | productType: '', |
| | | productSubType: '', |
| | | importantDistrictIdList: [], |
| | | orderNo: '', |
| | | status: '', |
| | | dateRange: [], |
| | |
| | | return 'currency' |
| | | } |
| | | |
| | | |
| | | const importantAreaCh=()=>{ |
| | | let checkedKeys = areaIdTreeRef.value!.getCheckedNodes(false, true) |
| | | if(checkedKeys&&checkedKeys.length>0&& query.unitProject.length>0){ |
| | | query.importantDistrictIdList=[] |
| | | checkedKeys.forEach((item:any)=>{ |
| | | if(item.children&&item.children.length>0){ |
| | | query.importantDistrictIdList.push(item.value) |
| | | } |
| | | }) |
| | | } |
| | | } |
| | | |
| | | const importantAreaClear=()=>{ |
| | | query.unitProject = [] |
| | | query.importantDistrictIdList = [] |
| | | areaIdTreeRef.value.setCheckedKeys([]) |
| | | } |
| | | |
| | | // 获取行业领域选项 |
| | | const getIndustryOptions = async () => { |
| | | try { |
| | |
| | | try { |
| | | const res = await productApi.getCategoryByParent({ parentId: industryCode }) |
| | | if (res?.code === 200 && res.data) { |
| | | unitProjectOptions.value = res.data.map((item: any) => ({ |
| | | label: item.name, |
| | | value: item.id |
| | | })) |
| | | unitProjectOptions.value = handleIndustryData(res.data) |
| | | } |
| | | } catch (error) { |
| | | console.error('获取单位工程选项失败:', error) |
| | | unitProjectOptions.value = [] |
| | | } |
| | | } |
| | | |
| | | const handleIndustryData=(list:any)=>{ |
| | | if(list&& list.length>0){ |
| | | let data=list.map((item:any)=>{ |
| | | return { |
| | | label:item.name, |
| | | value:item.id, |
| | | parentId:item.parentId, |
| | | parentName:item.parentName, |
| | | children:item.childrenList?handleIndustryChildData(item,item.childrenList):[] |
| | | } |
| | | }) |
| | | return data |
| | | } |
| | | } |
| | | const handleIndustryChildData=(parentItem:any,childList:any)=>{ |
| | | if(childList&& childList.length>0){ |
| | | let data=childList.map((item:any)=>{ |
| | | return { |
| | | parentId:parentItem.id, |
| | | parentName:parentItem.name, |
| | | label:item.name, |
| | | value:item.id, |
| | | children:item.childrenList?handleIndustryChildData(item,item.childrenList):[] |
| | | } |
| | | }) |
| | | return data |
| | | } |
| | | } |
| | | |
| | |
| | | // 处理行业领域变化 |
| | | const handleIndustryChange = async (value: string) => { |
| | | // 清空单位工程选择 |
| | | query.unitProject = '' |
| | | query.unitProject = [] |
| | | query.importantDistrictIdList = [] |
| | | // 获取对应的单位工程选项 |
| | | await getUnitProjectOptions(value) |
| | | } |
| | |
| | | // 主订单行,合并所有列显示订单信息 |
| | | if (columnIndex === 0) { // 第一列,合并所有列 |
| | | return { |
| | | colspan: 8, // 总共8列:订单信息2列 + 购买方式2列 + 总价2列 + 期限1列 + 操作1列 |
| | | colspan: 7, // 总共7列:订单信息2列 + 购买方式2列 + 数量1列 + 期限1列 + 操作1列 |
| | | rowspan: 1 |
| | | } |
| | | } else { |
| | |
| | | } |
| | | } |
| | | } |
| | | } else if (columnIndex === 7) { // 操作列(第8列) |
| | | } else if (columnIndex === 6) { // 操作列(第7列) |
| | | // 找到当前子订单所属的主订单 |
| | | const parentOrder = row.parentOrder |
| | | if (parentOrder && parentOrder.subOrders) { |
| | |
| | | |
| | | // 搜索处理(接入真实后端) |
| | | const handleSearch = async () => { |
| | | const filterEvaluated = query.status === 'EVALUATED' |
| | | const payload: any = { |
| | | pageNum: page.current, |
| | | pageSize: page.size, |
| | |
| | | orderId: query.orderNo || undefined, |
| | | userId: userStore.getUserId ? userStore.getUserId : undefined, |
| | | } |
| | | if (query.status) payload.orderStatus = statusUiToServer[query.status] |
| | | if (query.status) { |
| | | payload.orderStatus = filterEvaluated ? OrderStatus.COMPLETED : statusUiToServer[query.status] |
| | | } |
| | | if (Array.isArray(query.dateRange) && query.dateRange.length === 2) { |
| | | payload.applyTimeStart = query.dateRange[0] |
| | | payload.applyTimeEnd = query.dateRange[1] |
| | |
| | | |
| | | // 添加产品条件查询 |
| | | if (query.industry) payload.industryId = query.industry |
| | | if (query.unitProject) payload.unitProjectId = query.unitProject |
| | | if (query.unitProject.length > 0) payload.unitProjectId = query.unitProject |
| | | if (query.importantDistrictIdList.length > 0) payload.importantDistrictId = query.importantDistrictIdList |
| | | if (query.productType) payload.productTypeId = query.productType |
| | | if (query.productSubType) payload.productSubTypeId = query.productSubType |
| | | |
| | | // 根据是否有产品条件选择不同的API |
| | | const hasProductConditions = query.industry || query.unitProject || query.productType || query.productSubType |
| | | const hasProductConditions = query.industry || query.unitProject.length > 0 || query.productType || query.productSubType |
| | | const apiMethod = hasProductConditions ? orderApi.getBuyerOrderPageWithProductConditions : orderApi.getBuyerOrderPage |
| | | |
| | | const res = (await apiMethod(payload)) as any |
| | | const pageData = res?.data |
| | | const list: any[] = Array.isArray(pageData?.list) ? pageData.list : [] |
| | | let list: any[] = Array.isArray(pageData?.list) ? pageData.list : [] |
| | | // 若筛选“已评价”,先以已完成查询,再在前端按已评价过滤 |
| | | if (filterEvaluated) { |
| | | list = list.filter((order: any) => order?.isEvaluate === '已评价') |
| | | } |
| | | page.total = Number(pageData?.total || 0) |
| | | |
| | | const flatData: any[] = [] |
| | |
| | | Object.assign(query, { |
| | | productName: '', |
| | | industry: '', |
| | | unitProject: '', |
| | | unitProject: [], |
| | | productType: '', |
| | | productSubType: '', |
| | | importantDistrictIdList: [], |
| | | orderNo: '', |
| | | status: '', |
| | | dateRange: [], |
| | |
| | | .period-info { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | gap: 8px; |
| | | font-size: 12px; |
| | | |
| | |
| | | font-size: 12px; |
| | | color: #303133; |
| | | font-weight: 500; |
| | | text-align: center; |
| | | } |
| | | |
| | | .pagination-container { |
| | |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="提供者">{{ detail.supplier }}</el-descriptions-item> |
| | | <el-descriptions-item label="行业领域">{{ detail.industry }}</el-descriptions-item> |
| | | <el-descriptions-item label="单位工程">{{ detail.projectUnit }}</el-descriptions-item> |
| | | <el-descriptions-item label="单位工程"> |
| | | <el-tooltip effect="dark" :content="detail.projectUnit || '-'" placement="top" :disabled="!(detail.projectUnit && String(detail.projectUnit).trim())" popper-class="tooltip-wrap"> |
| | | <div class="ellipsis-1">{{ detail.projectUnit || '-' }}</div> |
| | | </el-tooltip> |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="产品类型">{{ detail.productType || '-' }}</el-descriptions-item> |
| | | <el-descriptions-item label="产品简介"> |
| | | <div class="desc-wrap">{{ detail.productDesc }}</div> |
| | | <el-tooltip effect="dark" :content="detail.productDesc || '-'" placement="top" :disabled="!(detail.productDesc && String(detail.productDesc).trim())" popper-class="tooltip-wrap" trigger="click"> |
| | | <div class="desc-wrap ellipsis-3">{{ detail.productDesc || '-' }}</div> |
| | | </el-tooltip> |
| | | </el-descriptions-item> |
| | | </el-descriptions> |
| | | |
| | |
| | | </div> |
| | | |
| | | </el-card> |
| | | |
| | | <!-- 交易评价(当已评价时显示) --> |
| | | <el-card class="mt15" shadow="never" v-if="showEvaluation"> |
| | | <div class="title">交易评价</div> |
| | | <div class="evaluation-content"> |
| | | <div class="evaluation-form"> |
| | | <div class="rating-section"> |
| | | <div class="rating-items"> |
| | | <div class="rating-row"> |
| | | <div class="rating-item"> |
| | | <label class="required">综合评分:</label> |
| | | <el-rate :model-value="evaluation.overallRating" :max="5" disabled :colors="['#99A9BF', '#F7BA2A', '#FF9900']" /> |
| | | </div> |
| | | <div class="rating-item"> |
| | | <label class="required">服务评分:</label> |
| | | <el-rate :model-value="evaluation.serviceRating" :max="5" disabled :colors="['#99A9BF', '#F7BA2A', '#FF9900']" /> |
| | | </div> |
| | | </div> |
| | | <div class="rating-row"> |
| | | <div class="rating-item"> |
| | | <label class="required">质量评分:</label> |
| | | <el-rate :model-value="evaluation.qualityRating" :max="5" disabled :colors="['#99A9BF', '#F7BA2A', '#FF9900']" /> |
| | | </div> |
| | | <div class="rating-item"> |
| | | <label class="required">速度评分:</label> |
| | | <el-rate :model-value="evaluation.speedRating" :max="5" disabled :colors="['#99A9BF', '#F7BA2A', '#FF9900']" /> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <div class="form-item"> |
| | | <label class="required">评价内容:</label> |
| | | <div class="eval-text">{{ evaluation.content || '-' }}</div> |
| | | </div> |
| | | |
| | | <div class="form-item"> |
| | | <label>其他信息:</label> |
| | | <div class="eval-meta"> |
| | | <span>是否匿名:{{ evaluation.isAnonymous ? '是' : '否' }}</span> |
| | | <span class="split">|</span> |
| | | <span>评价时间:{{ evaluation.evaluateTime || '-' }}</span> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </el-card> |
| | | <!-- 返回按钮 --> |
| | | <div class="action-buttons"> |
| | | <el-button @click="goBack">返回</el-button> |
| | |
| | | const route = useRoute() |
| | | const router = useRouter() |
| | | const detail = reactive<any>({ items: [], records: [], nodes: [] }) |
| | | const evaluation = reactive<any>({ |
| | | content: '', |
| | | overallRating: 0, |
| | | serviceRating: 0, |
| | | qualityRating: 0, |
| | | speedRating: 0, |
| | | isAnonymous: false, |
| | | evaluateTime: '' |
| | | }) |
| | | const orderTableWrapRef = ref<HTMLElement | null>(null) |
| | | const activeTab = ref('records') |
| | | const userStore = useUserInfo() |
| | |
| | | const statusOrder = ['WAIT_UPLOAD', 'WAIT_AUTHORIZE', 'WAIT_CONFIRM', 'COMPLETED', 'EVALUATED'] |
| | | const currentStatus = statusServerToUi[statusName] |
| | | return currentStatus && statusOrder.indexOf(currentStatus) >= statusOrder.indexOf('WAIT_CONFIRM') |
| | | }) |
| | | |
| | | // 是否显示评价卡片(已评价时显示) |
| | | const showEvaluation = computed(() => { |
| | | return (detail.isEvaluate === '已评价') |
| | | }) |
| | | |
| | | // 计算表格数据,添加汇总行 |
| | |
| | | projectUnit: data.projectUnit || '-', |
| | | productType: data.productType || '-', |
| | | productDesc: data.productDesc || '-', |
| | | isEvaluate: data.isEvaluate || '未评价' |
| | | } |
| | | |
| | | // 明细项映射 |
| | |
| | | nodes: [], |
| | | workflowId: data.workflowId || data.processinstId || '' |
| | | }) |
| | | |
| | | // 映射交易评价信息(如果存在) |
| | | if (data.evaluation) { |
| | | evaluation.content = data.evaluation.content || '' |
| | | evaluation.overallRating = Number(data.evaluation.rating || data.evaluation.overallRating || 0) |
| | | evaluation.serviceRating = Number(data.evaluation.serviceRating || 0) |
| | | evaluation.qualityRating = Number(data.evaluation.qualityRating || 0) |
| | | // 后端为 deliveryRating,对齐前端 speedRating 命名 |
| | | evaluation.speedRating = Number(data.evaluation.deliveryRating || data.evaluation.speedRating || 0) |
| | | evaluation.isAnonymous = Boolean(data.evaluation.isAnonymous) |
| | | evaluation.evaluateTime = formatDateTime((data.evaluation.replyTime || data.evaluation.createdAt || data.evaluation.createTime) as any) |
| | | } |
| | | |
| | | // 初始化交易信息备注数据 |
| | | remarkItems.value = (detail.items || []).map((item: any, index: number) => { |
| | |
| | | line-height: 22px; |
| | | } |
| | | |
| | | /* 单行省略(用于“单位工程”) */ |
| | | .ellipsis-1 { |
| | | max-height: 22px; |
| | | overflow: hidden; |
| | | text-overflow: ellipsis; |
| | | white-space: nowrap; |
| | | } |
| | | |
| | | /* 多行省略(用于“产品简介”,固定为3行,可按需调整) */ |
| | | .ellipsis-3 { |
| | | display: -webkit-box; |
| | | line-clamp: 3; |
| | | -webkit-line-clamp: 3; |
| | | -webkit-box-orient: vertical; |
| | | overflow: hidden; |
| | | } |
| | | |
| | | |
| | | |
| | | /* 审批追踪标签页样式 */ |
| | | .approval-tabs { |
| | | margin-top: 15px; |
| | |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="" class="col-17"> |
| | | <el-select v-model="query.unitProject" placeholder="请选择单位工程" clearable style="width: 100%"> |
| | | <el-option v-for="item in unitProjectOptions" :key="item.value" :label="item.label" :value="item.value" /> |
| | | </el-select> |
| | | <!-- <el-select v-model="query.unitProject" placeholder="请选择单位工程" clearable style="width: 100%">--> |
| | | <!-- <el-option v-for="item in unitProjectOptions" :key="item.value" :label="item.label" :value="item.value" />--> |
| | | <!-- </el-select>--> |
| | | <el-tree-select |
| | | ref="areaIdTreeRef" |
| | | v-model="query.unitProject" |
| | | :data="unitProjectOptions" |
| | | placeholder="请选择单位工程" |
| | | multiple |
| | | collapse-tags |
| | | collapse-tags-tooltip |
| | | clearable |
| | | :default-expand-all="true" |
| | | :render-after-expand="false" |
| | | show-checkbox |
| | | style="width: 170px;" |
| | | @change="importantAreaCh" |
| | | @clear="importantAreaClear" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="产品类型" class="col-30"> |
| | | <el-select v-model="query.productType" placeholder="请选择产品类型" clearable style="width: 100%" @change="handleProductTypeChange"> |
| | |
| | | </el-table-column> |
| | | </el-table-column> |
| | | |
| | | <!-- 总价 --> |
| | | <el-table-column label="总价" align="center"> |
| | | <el-table-column label="单价" prop="unitPrice" width="90"> |
| | | <!-- 单价(与“期限(年)”保持相同的父子表头结构) --> |
| | | <el-table-column label="单价" align="center" width="80"> |
| | | <el-table-column label="" prop="unitPrice" width="80"> |
| | | <template #default="{ row }"> |
| | | <div v-if="row.isSpacer" class="spacer-cell"></div> |
| | | <div v-else-if="!row.isMainOrder" class="price-info"> |
| | |
| | | </div> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="数量" prop="quantity" width="50"> |
| | | </el-table-column> |
| | | |
| | | <!-- 数量(与“期限(年)”保持相同的父子表头结构) --> |
| | | <el-table-column label="数量" align="center" width="80"> |
| | | <el-table-column label="" prop="quantity" width="80" align="center"> |
| | | <template #default="{ row }"> |
| | | <div v-if="row.isSpacer" class="spacer-cell"></div> |
| | | <div v-else-if="!row.isMainOrder" class="quantity">{{ row.quantity }}</div> |
| | |
| | | |
| | | <!-- 期限(年) --> |
| | | <el-table-column label="期限(年)" align="center" width="80"> |
| | | <el-table-column label="" prop="period" width="80"> |
| | | <el-table-column label="" prop="period" width="80" align="center"> |
| | | <template #default="{ row }"> |
| | | <div v-if="row.isSpacer" class="spacer-cell"></div> |
| | | <div v-else-if="!row.isMainOrder" class="period-info"> |
| | |
| | | |
| | | const router = useRouter() |
| | | const userStore = useUserInfo() |
| | | const areaIdTreeRef=ref() |
| | | |
| | | // 状态选项(更新为新的工作流程状态) |
| | | const statusOptions = [ |
| | |
| | | const query = reactive({ |
| | | productName: '', |
| | | industry: '', |
| | | unitProject: '', |
| | | unitProject: [] as string[], |
| | | productType: '', |
| | | productSubType: '', |
| | | importantDistrictIdList: [] as string[], |
| | | orderNo: '', |
| | | status: '', |
| | | dateRange: [], |
| | | dateRange: [] as string[], |
| | | }) |
| | | |
| | | // 分页信息 |
| | |
| | | try { |
| | | const res = await productApi.getCategoryByParent({ parentId: industryCode }) |
| | | if (res?.code === 200 && res.data) { |
| | | unitProjectOptions.value = res.data.map((item: any) => ({ |
| | | label: item.name, |
| | | value: item.id |
| | | })) |
| | | unitProjectOptions.value = handleIndustryData(res.data) |
| | | } |
| | | } catch (error) { |
| | | console.error('获取单位工程选项失败:', error) |
| | | unitProjectOptions.value = [] |
| | | } |
| | | } |
| | | |
| | | const handleIndustryData=(list:any)=>{ |
| | | if(list&& list.length>0){ |
| | | let data=list.map((item:any)=>{ |
| | | return { |
| | | label:item.name, |
| | | value:item.id, |
| | | parentId:item.parentId, |
| | | parentName:item.parentName, |
| | | children:item.childrenList?handleIndustryChildData(item,item.childrenList):[] |
| | | } |
| | | }) |
| | | return data |
| | | } |
| | | } |
| | | const handleIndustryChildData=(parentItem:any,childList:any)=>{ |
| | | if(childList&& childList.length>0){ |
| | | let data=childList.map((item:any)=>{ |
| | | return { |
| | | parentId:parentItem.id, |
| | | parentName:parentItem.name, |
| | | label:item.name, |
| | | value:item.id, |
| | | children:item.childrenList?handleIndustryChildData(item,item.childrenList):[] |
| | | } |
| | | }) |
| | | return data |
| | | } |
| | | } |
| | | |
| | |
| | | } |
| | | } |
| | | |
| | | const importantAreaCh=()=>{ |
| | | let checkedKeys = areaIdTreeRef.value!.getCheckedNodes(false, true) |
| | | if(checkedKeys&&checkedKeys.length>0&& query.unitProject.length>0){ |
| | | query.importantDistrictIdList=[] |
| | | checkedKeys.forEach((item:any)=>{ |
| | | if(item.children&&item.children.length>0){ |
| | | query.importantDistrictIdList.push(String(item.value)) |
| | | } |
| | | }) |
| | | } |
| | | } |
| | | |
| | | const importantAreaClear=()=>{ |
| | | query.unitProject = [] |
| | | query.importantDistrictIdList = [] |
| | | areaIdTreeRef.value.setCheckedKeys([]) |
| | | } |
| | | |
| | | // 处理行业领域变化 |
| | | const handleIndustryChange = async (value: string) => { |
| | | // 清空单位工程选择 |
| | | query.unitProject = '' |
| | | query.unitProject = [] |
| | | // 获取对应的单位工程选项 |
| | | await getUnitProjectOptions(value) |
| | | } |
| | |
| | | // 获取对应的产品子级选项 |
| | | // await getProductSubTypeOptions(value) |
| | | } |
| | | |
| | | |
| | | |
| | | // 获取状态类型 |
| | | const getStatusType = (status: string) => { |
| | |
| | | // 主订单行,合并所有列显示订单信息 |
| | | if (columnIndex === 0) { // 第一列,合并所有列 |
| | | return { |
| | | colspan: 8, // 总共8列:订单信息2列 + 购买方式2列 + 总价2列 + 期限1列 + 操作1列 |
| | | colspan: 8, // 总共8列:订单信息2列 + 购买方式2列 + 单价1列 + 数量1列 + 期限1列 + 操作1列 |
| | | rowspan: 1 |
| | | } |
| | | } else { |
| | |
| | | |
| | | // 添加产品条件查询 |
| | | if (query.industry) payload.industryId = query.industry |
| | | if (query.unitProject) payload.unitProjectId = query.unitProject |
| | | if (query.unitProject.length > 0) payload.unitProjectId = query.unitProject |
| | | if (query.importantDistrictIdList.length > 0) payload.importantDistrictId = query.importantDistrictIdList |
| | | if (query.productType) payload.productTypeId = query.productType |
| | | if (query.productSubType) payload.productSubTypeId = query.productSubType |
| | | |
| | | // 根据是否有产品条件选择不同的API |
| | | const hasProductConditions = query.industry || query.unitProject || query.productType || query.productSubType |
| | | const hasProductConditions = query.industry || query.unitProject.length > 0 || query.productType || query.productSubType |
| | | const apiMethod = hasProductConditions ? orderApi.getSellerOrderPageWithProductConditions : orderApi.getSellerOrderPage |
| | | |
| | | const res = (await apiMethod(payload)) as any |
| | |
| | | .period-info { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | gap: 8px; |
| | | font-size: 12px; |
| | | |
| | |
| | | // target:'http://10.209.233.16/admin',//信创正式 |
| | | // target: 'http://36.133.126.111:7099/api', //测试 |
| | | // target: 'https://zynlpt.ccccltd.cn/admin', // 正式 (要打开changeOrigin和rewrite) |
| | | // target: 'http://localhost:8089', |
| | | // target: 'http://localhost:8089', |
| | | target: 'http://36.133.126.111:7099/trade-api', |
| | | changeOrigin: true, // 允许跨域 |
| | | rewrite: (path) => path.replace(/^\/api/, '/'), //连测试环境要注释这行,连后端个人则打开 |