AddOrEditCheckItemForEquipment.vue 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929
  1. <template>
  2. <CustomDialog
  3. :model-value="modelValue"
  4. title="选择检验项目"
  5. width="80%"
  6. :before-close="handleClose"
  7. class="AddOrEditCheckItemForEquipmentDialog"
  8. >
  9. <el-tabs v-model="activeName">
  10. <el-tab-pane label="选择检验项目" name="selectCheckItem">
  11. <el-form :model="queryParams" ref="queryFormRef" class="view-info-form">
  12. <el-form-item label="设备类型" prop="equipmentCategory">
  13. <span class="info-text">{{ PressureBoilerEquipTypeMap[String(queryParams.equipmentCategory)] || '-' }}</span>
  14. </el-form-item>
  15. <el-form-item label="检验性质" prop="inspectionNature">
  16. <span class="info-text">{{
  17. Array.isArray(queryParams.inspectionNature)
  18. ? queryParams.inspectionNature
  19. .map(val => filterPressureBoilerCheckTypeMap[String(val)])
  20. .filter(Boolean)
  21. .join('、')
  22. : (filterPressureBoilerCheckTypeMap[String(queryParams.inspectionNature)] || '-')
  23. }}</span>
  24. </el-form-item>
  25. <el-form-item label="新增费用">
  26. <div class="flex items-center gap-4 mb-2">
  27. <span class="text-gray-600">应收法定金额: {{ formData.shouldAmount }}</span>
  28. <span class="text-gray-600">服务收费金额: {{ formData.serviceAmount }}</span>
  29. <span class="text-gray-600">免征费用: {{ formData.reduceFee }}</span>
  30. </div>
  31. </el-form-item>
  32. </el-form>
  33. <div class="checkItemContentWrapper" v-loading="checkItemListLoading">
  34. <div
  35. class="checkItemContent"
  36. v-for="checkItem in checkItemList"
  37. :key="checkItem.inspectionNature"
  38. >
  39. <div class="content-title">
  40. {{ checkItem.inspectionNatureName }}
  41. </div>
  42. <div class="inspection-grid">
  43. <!-- 标题行 -->
  44. <div class="grid-header">检验项目</div>
  45. <template v-if="checkItem.itemList.length > 0">
  46. <!-- Grid 容器 -->
  47. <div
  48. class="grid-container"
  49. :style="{
  50. 'grid-template-columns':
  51. checkItem.itemList.length < 5
  52. ? `repeat(${checkItem.itemList.length}, 1fr)`
  53. : `repeat(5, 1fr)`
  54. }"
  55. >
  56. <!-- 循环渲染子项(模拟数据) -->
  57. <div class="grid-item" v-for="(item, index) in checkItem.itemList" :key="index">
  58. <!-- <el-checkbox-->
  59. <!-- :disabled="selectedIds.includes(item.templateId) && item.reportType === 100"-->
  60. <!-- v-model="item.use"-->
  61. <!-- @change="(val) => handleCheckItemSelectedChange(item, val)"-->
  62. <!-- />-->
  63. <el-checkbox
  64. :disabled="item.isMainProject === '1'"
  65. v-model="item.use"
  66. @change="(val) => handleCheckItemSelectedChange(item, val)"
  67. />
  68. <div style="display: flex; align-items: center; gap: 4px;">
  69. <span v-if="item.isMainProject === '1'"
  70. style="display: inline-flex; align-items: center; justify-content: center; width: 20px; height: 20px; background-color: #6cbcf5; color: #fff; font-size: 12px; border-radius: 2px; font-weight: bold;">主</span>
  71. <span>{{ item.name }}</span>
  72. </div>
  73. <template
  74. v-if="
  75. true
  76. "
  77. >
  78. (
  79. <el-button link type="primary" @click="() => handleInputCalcField(item)"
  80. >费用:{{ getCheckItemFeeType(item) }}</el-button
  81. >
  82. )
  83. </template>
  84. </div>
  85. </div>
  86. </template>
  87. <el-empty v-else :description="`暂无【${checkItem.inspectionNatureName}】检验项目`" />
  88. </div>
  89. </div>
  90. </div>
  91. <div class="checker-box">
  92. 检验员:
  93. <span>{{
  94. !currentSelectedChecker ? '-' : currentSelectedChecker?.member?.nickname
  95. }}</span>
  96. <el-button type="primary" link @click="handleSelectedNewChecker">请选择</el-button>
  97. </div>
  98. </el-tab-pane>
  99. <el-tab-pane label="检验意见通知书" name="checkNotice">
  100. <div class="checkItemContentWrapper" v-loading="checkItemListLoading">
  101. <div class="checkItemContent">
  102. <div class="inspection-grid">
  103. <div class="grid-header">检验意见通知书</div>
  104. <template v-if="reportCheckNoticeTemplateList.length > 0">
  105. <div
  106. class="grid-container"
  107. :style="{
  108. 'grid-template-columns':
  109. reportCheckNoticeTemplateList.length < 5
  110. ? `repeat(${reportCheckNoticeTemplateList.length}, 1fr)`
  111. : `repeat(5, 1fr)`
  112. }"
  113. >
  114. <div
  115. class="grid-item"
  116. v-for="(item, index) in reportCheckNoticeTemplateList"
  117. :key="item.id + index"
  118. >
  119. <el-checkbox
  120. :disabled="item.disabled"
  121. v-model="item.use"
  122. @change="(val) => handleJobGuideSelectedChange(item, val)"
  123. />
  124. <span>{{ item.reportName }}</span>
  125. </div>
  126. </div>
  127. </template>
  128. <el-empty v-else :description="`暂无【检验意见通知书】`" />
  129. </div>
  130. </div>
  131. </div>
  132. </el-tab-pane>
  133. <el-tab-pane label="作业指导书" name="jobGuide">
  134. <div class="checkItemContentWrapper" v-loading="checkItemListLoading">
  135. <div class="checkItemContent">
  136. <div class="inspection-grid">
  137. <div class="grid-header">作业指导书</div>
  138. <template v-if="jobGuideList.length > 0">
  139. <div
  140. class="grid-container"
  141. :style="{
  142. 'grid-template-columns':
  143. jobGuideList.length < 5
  144. ? `repeat(${jobGuideList.length}, 1fr)`
  145. : `repeat(5, 1fr)`
  146. }"
  147. >
  148. <!-- 循环渲染子项(模拟数据) -->
  149. <div
  150. class="grid-item"
  151. v-for="(item, index) in jobGuideList"
  152. :key="item.id + index"
  153. >
  154. <el-checkbox
  155. :disabled="item.disabled"
  156. v-model="item.use"
  157. @change="(val) => handleJobGuideSelectedChange(item, val)"
  158. />
  159. <span>{{ item.reportName }}</span>
  160. </div>
  161. </div>
  162. </template>
  163. <el-empty v-else :description="`暂无【作业指导书】`" />
  164. </div>
  165. </div>
  166. </div>
  167. </el-tab-pane>
  168. <!-- <el-tab-pane label="检验方案" name="checkScheme">-->
  169. <!-- <div class="checkItemContentWrapper" v-loading="checkItemListLoading">-->
  170. <!-- <div class="checkItemContent">-->
  171. <!-- <div class="inspection-grid">-->
  172. <!-- <div class="grid-header">检验方案</div>-->
  173. <!-- <template v-if="checkSchemeList.length > 0">-->
  174. <!-- <div-->
  175. <!-- class="grid-container"-->
  176. <!-- :style="{-->
  177. <!-- 'grid-template-columns':-->
  178. <!-- checkSchemeList.length < 5-->
  179. <!-- ? `repeat(${checkSchemeList.length}, 1fr)`-->
  180. <!-- : `repeat(5, 1fr)`-->
  181. <!-- }"-->
  182. <!-- >-->
  183. <!-- &lt;!&ndash; 循环渲染子项(模拟数据) &ndash;&gt;-->
  184. <!-- <div-->
  185. <!-- class="grid-item"-->
  186. <!-- v-for="(item, index) in checkSchemeList"-->
  187. <!-- :key="item.id + index"-->
  188. <!-- >-->
  189. <!-- <el-checkbox-->
  190. <!-- :disabled="item.disabled"-->
  191. <!-- v-model="item.use"-->
  192. <!-- @change="(val) => handleJobGuideSelectedChange(item, val)"-->
  193. <!-- />-->
  194. <!-- <span>{{ item.reportName }}</span>-->
  195. <!-- </div>-->
  196. <!-- </div>-->
  197. <!-- </template>-->
  198. <!-- <el-empty v-else :description="`暂无【检验方案】`" />-->
  199. <!-- </div>-->
  200. <!-- </div>-->
  201. <!-- </div>-->
  202. <!-- </el-tab-pane>-->
  203. </el-tabs>
  204. <template #footer>
  205. <el-button type="primary" :loading="loading" @click="handleConfirm">确认</el-button>
  206. <el-button @click="handleClose">取消</el-button>
  207. </template>
  208. </CustomDialog>
  209. <Teleport to="body">
  210. <!-- 费用计算弹窗 -->
  211. <calcCheckItemFee
  212. v-if="showCalcCheckItemFeeDialog"
  213. v-model="showCalcCheckItemFeeDialog"
  214. :equipmentId="equipmentIds.length === 1 ? equipmentIds[0] : ''"
  215. :templateInfo="calcTemplateInfo"
  216. :isBatch="isBatch"
  217. @save="handleSaveCalcFee"
  218. />
  219. </Teleport>
  220. <!-- 检验员选择弹窗 -->
  221. <CustomDialog
  222. v-if="checkerSelectVisible"
  223. v-model="checkerSelectVisible"
  224. title="选择检验员"
  225. append-to-body
  226. width="600px"
  227. class="AddOrEditCheckItemForEquipmentDialog"
  228. >
  229. <CheckerSelect
  230. v-model="currentSelectedCheckerIds"
  231. :max="1"
  232. @change="handleInspectionItemCheckerChange"
  233. />
  234. <template #footer>
  235. <el-button @click="checkerSelectVisible = false">取消</el-button>
  236. <el-button type="primary" @click="confirmCheckerSelect">确定</el-button>
  237. </template>
  238. </CustomDialog>
  239. </template>
  240. <script setup lang="ts">
  241. import CustomDialog from '@/components/CustomDialog/index.vue'
  242. import calcCheckItemFee from './calcCheckItemFee.vue'
  243. import CheckerSelect from '@/views/pressure2/equipboilerscheduling/components/CheckerSelect.vue'
  244. import { PressureBoilerCheckTypeMap, PressureReportType } from '@/utils/constants'
  245. import { ReportItemVO, BoilerTaskOrderApi } from '@/api/pressure2/boilertaskorder'
  246. import { useUserStore } from '@/store/modules/user'
  247. import { is, isEmpty } from '@/utils/is'
  248. import {
  249. getCheckSchemeList,
  250. getPressureReportTemplateListNoLimit
  251. } from '@/api/pressure2/reportTemplate' // 承压报告模板
  252. import { ElForm } from 'element-plus'
  253. import {DICT_TYPE, getStrDictOptions} from "@/utils/dict";
  254. const { queryCheckItemList } = BoilerTaskOrderApi
  255. //锅炉类型
  256. const PressureBoilerEquipType = {
  257. BOILER: 300
  258. }
  259. const PressureBoilerEquipTypeMap = {
  260. [PressureBoilerEquipType.BOILER]: '锅炉'
  261. }
  262. const userStore = useUserStore()
  263. const props = defineProps({
  264. modelValue: {
  265. type: Boolean,
  266. required: true
  267. },
  268. orderInfo: {
  269. type: Object as PropType<Recordable>,
  270. default: () => ({})
  271. },
  272. selectedIds: {
  273. type: Array,
  274. default: () => []
  275. },
  276. equipmentIds: {
  277. type: Array as PropType<string[]>,
  278. default: () => []
  279. },
  280. orderItemIds: {
  281. type: Array as PropType<string[]>,
  282. default: () => []
  283. },
  284. taskOrderItem: {
  285. type: Object,
  286. default: () => ({})
  287. },
  288. reportList: {
  289. type: Array as PropType<(ReportItemVO & OtherParams)[]>,
  290. default: () => [] as (ReportItemVO & OtherParams)[]
  291. },
  292. allReportList: {
  293. type: Array as PropType<(ReportItemVO & OtherParams)[]>,
  294. default: () => [] as (ReportItemVO & OtherParams)[]
  295. },
  296. // 任务单批量添加
  297. isBatch: {
  298. type: Boolean,
  299. default: false
  300. }
  301. })
  302. const emit = defineEmits(['update:modelValue', 'refresh'])
  303. type ActiveName = 'selectCheckItem' | 'checkNotice' | 'jobGuide' | 'checkScheme' | 'subProject'
  304. const activeName = ref<ActiveName>('selectCheckItem')
  305. const formData = ref({
  306. shouldAmount:0,
  307. serviceAmount:0,
  308. reduceFee:0
  309. })
  310. const filterPressureBoilerCheckTypeMap = computed(() => {
  311. return Object.fromEntries(
  312. Object.entries(PressureBoilerCheckTypeMap).filter(([value, label]) => {
  313. return value
  314. })
  315. )
  316. })
  317. // 是否为检验录入页面
  318. //const isCheckInputPage = computed(() => route.name === 'CheckerTaskDetail')
  319. const currentSelectedCheckerIds = ref<string[]>([])
  320. // 查询参数
  321. const queryParams = ref<Recordable>({
  322. equipmentCategory: 300,
  323. inspectionNature: []
  324. })
  325. const subProjectFormRef = ref<InstanceType<typeof ElForm>>()
  326. const subProjectParams = ref<Recordable>({
  327. subcontractedName: '',
  328. fee: undefined,
  329. fileList: []
  330. })
  331. const isSubProjectAddChecker = ref(false)
  332. const checkItemList = ref<any[]>([])
  333. const selectedCheckItem = ref<any[]>([])
  334. const getCheckItemFeeType = computed(() => {
  335. return ({ isAutoAmount, fee }) => {
  336. if (is(fee, 'Number')) return fee
  337. else if (is(fee, 'Null') && isAutoAmount === '1') return '录入计算'
  338. else return '无'
  339. }
  340. })
  341. // 复选框的变化
  342. const handleCheckItemSelectedChange = (checkItem, selected) => {
  343. if (
  344. selected &&
  345. selectedCheckItem.value.findIndex((item) => item.templateId === checkItem.templateId) < 0
  346. ) {
  347. selectedCheckItem.value.push(checkItem)
  348. } else if (
  349. !selected &&
  350. selectedCheckItem.value.findIndex((item) => item.templateId === checkItem.templateId) >= 0
  351. ) {
  352. const index = selectedCheckItem.value.findIndex(
  353. (item) => item.templateId === checkItem.templateId
  354. )
  355. selectedCheckItem.value.splice(index, 1)
  356. }
  357. calculateAmounts()
  358. }
  359. const checkItemListLoading = ref(false)
  360. // 查询项目列表
  361. const handleQueryCheckItemList = async (checkType) => {
  362. // 获取统一的设备类型,如果列表为空则设为 undefined
  363. const equipType = props.orderInfo.orderItems?.length > 0 ? props.orderInfo?.orderItems[0].type : props.taskOrderItem.type
  364. const params = {
  365. orderId: props.orderInfo?.id,
  366. itemIds: props.equipmentIds,
  367. equipmentCategory: queryParams.value.equipmentCategory,
  368. inspectionNature: [checkType],
  369. equipType:equipType
  370. }
  371. const queryResult = await queryCheckItemList(params)
  372. //console.log(queryResult)
  373. checkItemList.value.push({
  374. inspectionNatureName: filterPressureBoilerCheckTypeMap.value[checkType] + " 法定收费项目",
  375. inspectionNature: checkType,
  376. type: '1',
  377. itemList: (queryResult || []).map((item) => ({
  378. ...item,
  379. isAutoAmount: props.isBatch ? '0' : item.isAutoAmount,
  380. inspectionNature: checkType,
  381. // use: props.equipmentIds.length > 1 ? false : props.selectedIds.includes(item.templateId) && item.reportType === 100
  382. //use: props.selectedIds.includes(item.templateId)
  383. use:false,
  384. type: '1'
  385. }))
  386. })
  387. checkItemList.value.push({
  388. inspectionNatureName: filterPressureBoilerCheckTypeMap.value[checkType] + " 服务收费项目",
  389. inspectionNature: checkType,
  390. type: '2',
  391. itemList: (queryResult || []).map((item) => ({
  392. ...item,
  393. isAutoAmount: props.isBatch ? '0' : item.isAutoAmount,
  394. inspectionNature: checkType,
  395. // use: props.equipmentIds.length > 1 ? false : props.selectedIds.includes(item.templateId) && item.reportType === 100
  396. //use: props.selectedIds.includes(item.templateId)
  397. use:false,
  398. type: '2'
  399. }))
  400. })
  401. }
  402. // 获取检验意见通知书模板内容
  403. const reportCheckNoticeTemplateList = ref<any[]>([])
  404. const getReportCheckNoticeTemplateList = async () => {
  405. const params = {
  406. type: '3',
  407. pageNo: 1,
  408. pageSize: 100,
  409. status: 200,
  410. reportType : 400
  411. }
  412. getPressureReportTemplateListNoLimit(params)
  413. .then((res) => {
  414. reportCheckNoticeTemplateList.value = res.map((item) => ({
  415. ...item,
  416. reportName: item.tbName,
  417. disabled: props.selectedIds.includes(item.id),
  418. use: props.selectedIds.includes(item.id)
  419. }))
  420. })
  421. .catch(() => {
  422. reportCheckNoticeTemplateList.value = []
  423. console.log('获取检验意见通知书模板内容失败')
  424. })
  425. }
  426. // 获取检验方案列表
  427. const orderReportIdList = ref<string[]>([])
  428. const getCheckSchemeData = async () => {
  429. const params = {
  430. taskStatus: 800,
  431. orderId: props.orderInfo?.id
  432. }
  433. getCheckSchemeList(params)
  434. .then((res) => {
  435. const { list = [] } = res
  436. // console.log('list:log', list)
  437. // 已经存在的检验方案主键id
  438. // console.log('orderReportIdList', props)
  439. // orderReportIdList.value = (props.allReportList
  440. // .filter((x) => x.reportType === PressureReportType['INSPECTIONPLAN'] && x.orderReportId)
  441. // .map((item) => item.orderReportId) as string[])
  442. checkSchemeList.value = list
  443. .filter((x) => x.reportType === PressureReportType['INSPECTIONPLAN'])
  444. .map((v) => {
  445. return {
  446. ...v,
  447. disabled: props.selectedIds.includes(v.templateId),
  448. use: props.selectedIds.includes(v.templateId)
  449. }
  450. })
  451. })
  452. .catch(() => {
  453. reportCheckNoticeTemplateList.value = []
  454. console.log('获取检验意见通知书模板内容失败')
  455. })
  456. }
  457. watch(
  458. () => props.modelValue,
  459. (newVal) => {
  460. if (newVal) {
  461. getReportCheckNoticeTemplateList()
  462. getCheckSchemeData()
  463. }
  464. },
  465. {
  466. immediate: true
  467. }
  468. )
  469. watch(
  470. () => [props.orderInfo, props.equipmentIds],
  471. ([orderInfo, equipmentIds]: [Recordable, string[]]) => {
  472. if (!Object.keys(orderInfo).length || !equipmentIds.length) return
  473. queryParams.value.inspectionNature = [orderInfo?.checkType]
  474. },
  475. {
  476. immediate: true
  477. }
  478. )
  479. // 检验性质发生改变之后,获取检验项目列表
  480. watch(
  481. () => queryParams.value.inspectionNature,
  482. async (inspectionNature) => {
  483. checkItemList.value = []
  484. if (inspectionNature.length === 0) {
  485. return
  486. }
  487. checkItemListLoading.value = true
  488. for (const checkType of inspectionNature) {
  489. await handleQueryCheckItemList(checkType)
  490. }
  491. checkItemListLoading.value = false
  492. },
  493. {
  494. immediate: true
  495. }
  496. )
  497. // 计算费用弹窗
  498. const showCalcCheckItemFeeDialog = ref(false)
  499. const calcTemplateInfo = ref({})
  500. const handleInputCalcField = (item) => {
  501. showCalcCheckItemFeeDialog.value = true
  502. calcTemplateInfo.value = item
  503. }
  504. // 保存费用计算回调
  505. const handleSaveCalcFee = (templateInfo) => {
  506. for (const checkItem of checkItemList.value) {
  507. if (checkItem.inspectionNature !== templateInfo.inspectionNature) continue
  508. for (const item of checkItem.itemList) {
  509. if (item.templateId !== templateInfo.templateId) continue
  510. item.fee = templateInfo.fee
  511. }
  512. }
  513. calculateAmounts()
  514. }
  515. const calculateAmounts = () => {
  516. // 分离法定收费项目和服务收费项目
  517. const find = checkItemList?.value.find(item => item.type === '1');
  518. if (!find) return;
  519. const statutoryItems = find.itemList.filter(item => item.use)
  520. const find1 = checkItemList?.value.find(item => item.type === '2');
  521. if (!find1) return;
  522. const serviceItems = find1.itemList.filter(item => item.use)
  523. // 计算法定金额总和
  524. const totalStatutoryAmount = statutoryItems.reduce((sum, item) => sum + (item.fee * (item.quantity || 1) || 0), 0)
  525. // 计算服务收费金额总和
  526. const totalServiceAmount = serviceItems.reduce((sum, item) => sum + (item.fee * (item.quantity || 1) || 0), 0)
  527. if (props.orderInfo.feeNature === '1') {
  528. // 免征:免征费用=应收法定金额,应收法定金额=0
  529. formData.value.reduceFee = totalStatutoryAmount
  530. formData.value.shouldAmount = 0
  531. } else {
  532. // 不免征:免征费用=0,应收法定金额=总金额
  533. formData.value.reduceFee = 0
  534. formData.value.shouldAmount = totalStatutoryAmount
  535. }
  536. formData.value.serviceAmount = totalServiceAmount
  537. }
  538. // 选择检验员
  539. const checkerSelectVisible = ref(false)
  540. const currentSelectedChecker = ref<any>(null)
  541. const tempSaveCheckerInfo = ref(null)
  542. const handleInspectionItemCheckerChange = (checkerInfo) => {
  543. //console.log('checkerInfo:log', checkerInfo)
  544. // tempSaveCheckerInfo.value = checkerInfo?.[0]?.member
  545. tempSaveCheckerInfo.value = checkerInfo?.[0]
  546. }
  547. const handleSelectedNewChecker = () => {
  548. checkerSelectVisible.value = true
  549. }
  550. const confirmCheckerSelect = () => {
  551. // 分包项目进行区分
  552. if (isSubProjectAddChecker.value) {
  553. subProjectParams.value.subSelectedChecker = tempSaveCheckerInfo.value
  554. } else {
  555. currentSelectedChecker.value = tempSaveCheckerInfo.value
  556. }
  557. isSubProjectAddChecker.value = false
  558. checkerSelectVisible.value = false
  559. }
  560. // [PressureReportType['WORKINSTRUCTION'], PressureReportType['INSPECTIONPLAN']]
  561. // 作业指导书列表
  562. type OtherParams = { use: boolean; disabled: boolean; orderReportId?: string }
  563. const jobGuideList = ref<(ReportItemVO & OtherParams)[]>([])
  564. const handleJobGuideSelectedChange = (item, val) => {}
  565. // 检验方案列表
  566. const checkSchemeList = ref<(ReportItemVO & OtherParams)[]>([])
  567. watch(
  568. () => [props.allReportList, props.selectedIds],
  569. ([allReportList, selectedIds]: [ReportItemVO[], string[]]) => {
  570. //@ts-ignore
  571. jobGuideList.value = allReportList
  572. .filter((x) => x.reportType === PressureReportType['WORKINSTRUCTION'])
  573. .map((v) => ({
  574. ...v,
  575. disabled: selectedIds.includes(v.templateId || v.id),
  576. use: selectedIds.includes(v.templateId || v.id)
  577. }))
  578. },
  579. {
  580. immediate: true
  581. }
  582. )
  583. onMounted(() => {
  584. currentSelectedChecker.value = userStore.getUser
  585. })
  586. // 关闭弹窗
  587. const handleClose = () => {
  588. emit('update:modelValue', false)
  589. }
  590. const checkNoticeBookConfirm = () => {
  591. const addRows = reportCheckNoticeTemplateList.value
  592. .filter((x) => x.use)
  593. .filter((v) => !props.selectedIds.includes(v.id))
  594. if (!addRows.length) return handleClose()
  595. const itemList = props.orderItemIds
  596. .map((orderItemId) => {
  597. return addRows.map((x) => ({
  598. templateId: x.id,
  599. orderItemId
  600. }))
  601. })
  602. .flat(Infinity)
  603. const params = {
  604. itemList
  605. }
  606. loading.value = true
  607. //BoilerTaskOrderApi.addReportV2(params)
  608. BoilerTaskOrderApi.addReportV3(params)
  609. .then((res) => {
  610. ElMessage.success(`添加成功`)
  611. emit('refresh')
  612. handleClose()
  613. })
  614. .finally(() => {
  615. loading.value = false
  616. })
  617. .catch(() => {
  618. ElMessage.error('添加失败')
  619. })
  620. }
  621. // 检验意见通知书/意见指导书/检验方案提交
  622. const jobGuideOrCheckSchemeConfirm = () => {
  623. if (activeName.value === 'checkNotice') {
  624. // 检验意见通知书提交
  625. return checkNoticeBookConfirm()
  626. }
  627. const list =
  628. activeName.value === 'jobGuide'
  629. ? jobGuideList.value
  630. : activeName.value === 'checkScheme'
  631. ? checkSchemeList.value
  632. : []
  633. if (activeName.value === 'jobGuide') {
  634. const addRows = list
  635. .filter((x) => x.use)
  636. .filter((v) => !props.selectedIds.includes(v.templateId || v.id))
  637. if (!addRows.length) return handleClose()
  638. loading.value = true
  639. BoilerTaskOrderApi.cancelReportRollbackStatus({ ids: addRows.map((x) => x.id) })
  640. .then(() => {
  641. ElMessage.success(`添加成功`)
  642. emit('refresh')
  643. handleClose()
  644. })
  645. .finally(() => {
  646. loading.value = false
  647. })
  648. .catch(() => {
  649. ElMessage.error('添加失败')
  650. })
  651. } else if (activeName.value === 'checkScheme') {
  652. const addRows = list
  653. .filter((x) => x.use)
  654. .filter((v) => !unref(orderReportIdList).includes(v.id))
  655. if (!addRows.length) return handleClose()
  656. loading.value = true
  657. const params = {
  658. itemList: addRows.map((x) => ({
  659. templateId: x.templateId || x.id,
  660. orderItemId: props.orderItemIds[0],
  661. orderReportId: x.id
  662. }))
  663. }
  664. loading.value = true
  665. //BoilerTaskOrderApi.addReportV2(params)
  666. BoilerTaskOrderApi.addReportV3(params)
  667. .then((res) => {
  668. ElMessage.success(`添加成功`)
  669. emit('refresh')
  670. handleClose()
  671. })
  672. .finally(() => {
  673. loading.value = false
  674. })
  675. }
  676. }
  677. const subProjectConfirm = () => {
  678. subProjectFormRef.value?.validate().then(async (validate) => {
  679. const { subSelectedChecker, fileList, fee, subcontractedName } = subProjectParams.value
  680. const uploadFileInfo = fileList[0]
  681. const manualUrl = uploadFileInfo.response.data
  682. const fileExt = uploadFileInfo.name.split('.').pop()?.toLowerCase()
  683. const fileTypeMap = { docx: '0', pdf: '1' }
  684. if (isEmpty(fileTypeMap[fileExt])) return ElMessage.error('请上传docx或pdf文件')
  685. const params: Recordable = {
  686. itemList: props.orderItemIds.map((orderItemId) => {
  687. return {
  688. fee,
  689. subcontractedName,
  690. manualUrl,
  691. orderItemId,
  692. fileType: fileTypeMap[fileExt],
  693. reportType: '900'
  694. }
  695. })
  696. }
  697. if (subSelectedChecker) {
  698. params.checkId = subSelectedChecker?.member?.id
  699. params.groupTeamId = subSelectedChecker?.groupTeamId //小组id
  700. params.type = subSelectedChecker.isLeader ? 100 : 200 //是否为组长
  701. }
  702. loading.value = true
  703. //BoilerTaskOrderApi.addReportV2(params)
  704. BoilerTaskOrderApi.addReportV3(params)
  705. .then((res) => {
  706. ElMessage.success(`添加成功`)
  707. emit('refresh')
  708. handleClose()
  709. })
  710. .finally(() => {
  711. loading.value = false
  712. })
  713. })
  714. }
  715. const loading = ref(false)
  716. // 提交
  717. const handleConfirm = async () => {
  718. if (activeName.value === 'subProject') {
  719. return subProjectConfirm()
  720. }
  721. if (activeName.value !== 'selectCheckItem') {
  722. return jobGuideOrCheckSchemeConfirm()
  723. }
  724. try {
  725. const itemList = props.orderItemIds
  726. .map((orderItemId) => {
  727. return selectedCheckItem.value.map((x,index) => ({
  728. templateId: x.templateId,
  729. connectId: x.connectId,
  730. fee: x.fee,
  731. type: x.type,
  732. orderItemId
  733. }))
  734. })
  735. .flat(Infinity)
  736. if (!itemList.length) {
  737. handleClose()
  738. return
  739. }
  740. const params = {
  741. checkId: currentSelectedChecker.value?.member?.id,
  742. groupTeamId: currentSelectedChecker.value?.groupTeamId, //小组id
  743. type: currentSelectedChecker.value.isLeader ? 100 : 200, //是否为组长
  744. itemList,
  745. }
  746. loading.value = true
  747. //console.log(params)
  748. //const result = await BoilerTaskOrderApi.addReportV2(params)
  749. const result = await BoilerTaskOrderApi.addReportV3(params)
  750. loading.value = false
  751. if (result) {
  752. ElMessage.success(`添加成功`)
  753. emit('refresh')
  754. handleClose()
  755. }
  756. } catch (error) {
  757. loading.value = false
  758. ElMessage.error('添加检验项目失败')
  759. }
  760. }
  761. </script>
  762. <style lang="scss" scoped>
  763. .content-title {
  764. display: flex;
  765. justify-content: flex-start;
  766. align-items: center;
  767. width: 100%;
  768. height: 36px;
  769. line-height: 36px;
  770. background-color: var(--el-color-primary-light-9);
  771. &::before {
  772. content: '';
  773. height: 70%;
  774. width: 4px;
  775. margin-right: 12px;
  776. background-color: var(--el-color-primary);
  777. }
  778. }
  779. .customClass {
  780. background-color: #f60;
  781. :deep(.el-dialog__footer) {
  782. text-align: center;
  783. }
  784. }
  785. /* 外层容器 */
  786. .inspection-grid {
  787. width: 100%;
  788. padding: 16px;
  789. }
  790. /* 标题行 */
  791. .grid-header {
  792. font-size: 16px;
  793. font-weight: bold;
  794. text-align: center;
  795. height: 38px;
  796. line-height: 38px;
  797. border: 1px solid var(--el-border-color-light);
  798. border-bottom: 0;
  799. background-color: var(--el-color-primary-light-9);
  800. }
  801. /* Grid 容器核心配置 */
  802. .grid-container {
  803. display: grid;
  804. /* 5列等宽,列间距 12px,行间距 16px */
  805. grid-template-columns: repeat(5, 1fr);
  806. align-items: center; /* 垂直居中 */
  807. grid-gap: 1px;
  808. background-color: var(--el-border-color-light);
  809. border: 1px solid var(--el-border-color-light);
  810. }
  811. /* 子项布局:复选框 + 文本 + 图标 */
  812. .grid-item {
  813. display: flex;
  814. align-items: center;
  815. padding-left: 20px;
  816. padding-right: 12px;
  817. height: 52px;
  818. background-color: #fff;
  819. .el-checkbox {
  820. margin-right: 6px;
  821. }
  822. }
  823. /* 闪电图标样式(模拟,实际可替换为 SVG/Iconfont) */
  824. .icon-lightning {
  825. width: 24px;
  826. height: 24px;
  827. background-color: #ffd700; /* 金色背景 */
  828. mask: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M17 12h-2v3h-3v2h3v3h2v-3h3v-2h-3z"/></svg>')
  829. no-repeat center / contain;
  830. -webkit-mask: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M17 12h-2v3h-3v2h3v3h2v-3h3v-2h-3z"/></svg>')
  831. no-repeat center / contain;
  832. }
  833. /* 复选框样式优化(可选) */
  834. .grid-item input[type='checkbox'] {
  835. width: 16px;
  836. height: 16px;
  837. cursor: pointer;
  838. }
  839. .checker-box {
  840. display: flex;
  841. align-items: center;
  842. padding: 16px;
  843. .el-button {
  844. margin-left: 6px;
  845. }
  846. }
  847. :deep(.el-input-number) {
  848. width: 100%;
  849. .el-input__inner {
  850. text-align: left;
  851. }
  852. }
  853. // 查看信息表单样式优化
  854. .view-info-form {
  855. background: #f5f7fa;
  856. padding: 16px 20px;
  857. border-radius: 4px;
  858. margin-bottom: 16px;
  859. :deep(.el-form-item) {
  860. margin-right: 32px;
  861. margin-bottom: 0;
  862. }
  863. :deep(.el-form-item__label) {
  864. font-weight: 500;
  865. color: #606266;
  866. }
  867. .info-text {
  868. color: #303133;
  869. font-size: 14px;
  870. line-height: 1.5;
  871. word-break: break-all;
  872. }
  873. }
  874. </style>
  875. <style lang="scss">
  876. .AddOrEditCheckItemForEquipmentDialog {
  877. .el-dialog__footer {
  878. text-align: center;
  879. }
  880. }
  881. </style>