| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import request from "@/utils/request"; |
| | | |
| | | // å页æ¥è¯¢ |
| | | export function safeAccidentListPage(query) { |
| | | return request({ |
| | | url: "/safeAccident/page", |
| | | method: "get", |
| | | params: query, |
| | | }); |
| | | } |
| | | |
| | | |
| | | export function safeAccidentAdd(query) { |
| | | return request({ |
| | | url: '/safeAccident', |
| | | method: 'post', |
| | | data: query |
| | | }) |
| | | } |
| | | |
| | | export function safeAccidentUpdate(query) { |
| | | return request({ |
| | | url: '/safeAccident', |
| | | method: 'put', |
| | | data: query |
| | | }) |
| | | } |
| | | |
| | | export function safeAccidentDel(ids) { |
| | | return request({ |
| | | url: '/safeAccident/' + ids, |
| | | method: 'delete', |
| | | data: ids |
| | | }) |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | // åºæ¥é¢æ¡å®¡æ ¸é¡µé¢æ¥å£ |
| | | import request from "@/utils/request"; |
| | | |
| | | // å页æ¥è¯¢ |
| | | export function safeContingencyPlanListPage(query) { |
| | | return request({ |
| | | url: "/safeContingencyPlan/page", |
| | | method: "get", |
| | | params: query, |
| | | }); |
| | | } |
| | | |
| | | // æ°å¢åºæ¥é¢æ¡ |
| | | export function safeContingencyPlanAdd(query) { |
| | | return request({ |
| | | url: '/safeContingencyPlan', |
| | | method: 'post', |
| | | data: query |
| | | }) |
| | | } |
| | | |
| | | // ä¿®æ¹åºæ¥é¢æ¡ |
| | | export function safeContingencyPlanUpdate(query) { |
| | | return request({ |
| | | url: '/safeContingencyPlan', |
| | | method: 'put', |
| | | data: query |
| | | }) |
| | | } |
| | | |
| | | // å é¤åºæ¥é¢æ¡ |
| | | export function safeContingencyPlanDel(ids) { |
| | | return request({ |
| | | url: '/safeContingencyPlan/' + ids, |
| | | method: 'delete', |
| | | data: ids |
| | | }) |
| | | } |
| | |
| | | // æ¥è¯¢å·²ç»ç»å®å票çå¼ç¥¨å°è´¦ |
| | | export function bindInvoiceNoRegPage(query) { |
| | | return request({ |
| | | url: '/receiptPayment/bindInvoiceNoRegPage', |
| | | url: '/sales/product/listPageSalesLedger', |
| | | method: 'get', |
| | | params: query |
| | | }) |
| | |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/safeProduction/accidentReportingRecord/index", |
| | | "style": { |
| | | "navigationBarTitleText": "äºæ
æ¥åè®°å½", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/safeProduction/accidentReportingRecord/detail", |
| | | "style": { |
| | | "navigationBarTitleText": "äºæ
æ¥å详æ
", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/safeProduction/accidentReportingRecord/view", |
| | | "style": { |
| | | "navigationBarTitleText": "äºæ
æ¥å详æ
", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/cooperativeOffice/collaborativeApproval/index8", |
| | | "style": { |
| | | "navigationBarTitleText": "å±é©ä½ä¸å®¡æ¹", |
| | |
| | | "navigationBarTitleText": "å±é©ç©æè¯¦æ
", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/safeProduction/emergencyPlanReview/index", |
| | | "style": { |
| | | "navigationBarTitleText": "åºæ¥é¢æ¡å®¡æ ¸", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/safeProduction/emergencyPlanReview/detail", |
| | | "style": { |
| | | "navigationBarTitleText": "åºæ¥é¢æ¡è¯¦æ
", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/safeProduction/emergencyPlanReview/view", |
| | | "style": { |
| | | "navigationBarTitleText": "åºæ¥é¢æ¡è¯¦æ
", |
| | | "navigationStyle": "custom" |
| | | } |
| | | } |
| | | ], |
| | | "subPackages": [ |
| | |
| | | </view> |
| | | <!-- æµ®å¨æä½æé® --> |
| | | <view class="fab-button" |
| | | v-if="props.approveType != 5 && props.approveType != 6 && props.approveType != 7" |
| | | @click="handleAdd"> |
| | | <up-icon name="plus" |
| | | size="24" |
| | |
| | | icon: "/static/images/icon/guzhangfenxi@2x.png", |
| | | label: "å±é©ç©æ", |
| | | }, |
| | | { |
| | | icon: "/static/images/icon/guzhangfenxi@2x.png", |
| | | label: "åºæ¥é¢æ¡", |
| | | }, |
| | | { |
| | | icon: "/static/images/icon/guzhangfenxi@2x.png", |
| | | label: "äºæ
䏿¥", |
| | | }, |
| | | ]); |
| | | // åååå
¬åè½æ°æ® |
| | | const collaborationItems = reactive([ |
| | |
| | | url: "/pages/safeProduction/hazardousMaterialsControl/index", |
| | | }); |
| | | break; |
| | | case "åºæ¥é¢æ¡": |
| | | uni.navigateTo({ |
| | | url: "/pages/safeProduction/emergencyPlanReview/index", |
| | | }); |
| | | break; |
| | | case "äºæ
䏿¥": |
| | | uni.navigateTo({ |
| | | url: "/pages/safeProduction/accidentReportingRecord/index", |
| | | }); |
| | | break; |
| | | default: |
| | | uni.showToast({ |
| | | title: `ç¹å»äº${item.label}`, |
| | |
| | | size="small" |
| | | @click="addProduct" |
| | | class="add-btn" |
| | | v-if="operationType !== 'view'"> |
| | | v-if="canEditProducts"> |
| | | æ°å¢ |
| | | </up-button> |
| | | </view> |
| | |
| | | </view> |
| | | <!-- æä½æé® --> |
| | | <view class="product-actions" |
| | | v-if="operationType !== 'view'"> |
| | | v-if="canEditProducts"> |
| | | <up-button type="error" |
| | | size="mini" |
| | | @click="removeProduct(idx)" |
| | |
| | | <up-input v-model="product.productCategory" |
| | | readonly |
| | | placeholder="è¯·éæ©" |
| | | :disabled="!canEditProducts" |
| | | @click="openCategoryPicker(idx)" /> |
| | | <template #right> |
| | | <up-icon name="arrow-right" |
| | | v-if="canEditProducts" |
| | | @click="showCategoryPicker = true"></up-icon> |
| | | </template> |
| | | </up-form-item> |
| | |
| | | <up-input v-model="product.specificationModel" |
| | | readonly |
| | | placeholder="è¯·éæ©" |
| | | :disabled="!canEditProducts" |
| | | @click="openSpecificationPicker(idx)" /> |
| | | <template #right> |
| | | <up-icon name="arrow-right" |
| | | v-if="canEditProducts" |
| | | @click="showSpecificationPicker = true"></up-icon> |
| | | </template> |
| | | </up-form-item> |
| | |
| | | required |
| | | :rules="productRules"> |
| | | <up-input v-model="product.unit" |
| | | :disabled="!canEditProducts" |
| | | placeholder="请è¾å
¥" /> |
| | | </up-form-item> |
| | | <!-- ç¨ç --> |
| | |
| | | <up-input v-model="product.taxRate" |
| | | readonly |
| | | placeholder="è¯·éæ©" |
| | | :disabled="!canEditProducts" |
| | | @click="openTaxRatePicker(idx)" /> |
| | | <template #right> |
| | | <up-icon name="arrow-right" |
| | | v-if="canEditProducts" |
| | | @click="showTaxRatePicker = true"></up-icon> |
| | | </template> |
| | | </up-form-item> |
| | |
| | | :rules="productRules"> |
| | | <up-input v-model="product.taxInclusiveUnitPrice" |
| | | type="number" |
| | | :disabled="!canEditProducts" |
| | | placeholder="请è¾å
¥" |
| | | @blur="formatTaxPrice(idx)" /> |
| | | </up-form-item> |
| | |
| | | :rules="productRules"> |
| | | <up-input v-model="product.quantity" |
| | | type="number" |
| | | :disabled="!canEditProducts" |
| | | placeholder="请è¾å
¥" |
| | | @blur="formatAmount(idx)" /> |
| | | </up-form-item> |
| | |
| | | :rules="productRules"> |
| | | <up-input v-model="product.taxInclusiveTotalPrice" |
| | | type="number" |
| | | :disabled="!canEditProducts" |
| | | placeholder="请è¾å
¥" |
| | | @blur="formatTaxTotal(idx)" /> |
| | | </up-form-item> |
| | |
| | | :rules="productRules"> |
| | | <up-input v-model="product.taxExclusiveTotalPrice" |
| | | type="number" |
| | | :disabled="!canEditProducts" |
| | | placeholder="请è¾å
¥" |
| | | @blur="formatNoTaxTotal(idx)" /> |
| | | </up-form-item> |
| | |
| | | <up-input v-model="product.invoiceType" |
| | | readonly |
| | | placeholder="è¯·éæ©" |
| | | :disabled="!canEditProducts" |
| | | @click="openInvoiceTypePicker(idx)" /> |
| | | <template #right> |
| | | <up-icon name="arrow-right" |
| | | v-if="canEditProducts" |
| | | @click="showInvoiceTypePicker = true"></up-icon> |
| | | </template> |
| | | </up-form-item> |
| | |
| | | :rules="productRules"> |
| | | <up-input v-model="product.warnNum" |
| | | type="number" |
| | | :disabled="!canEditProducts" |
| | | placeholder="请è¾å
¥" /> |
| | | </up-form-item> |
| | | <up-form-item label="æ¯å¦è´¨æ£" |
| | |
| | | required |
| | | :rules="productRules"> |
| | | <u-radio-group v-model="product.isChecked" |
| | | :disabled="!canEditProducts" |
| | | placement="row" |
| | | @change="groupChange"> |
| | | <u-radio :customStyle="{marginRight: '40rpx'}" |
| | | label="æ¯" |
| | | :disabled="!canEditProducts" |
| | | :name="true"> |
| | | </u-radio> |
| | | <u-radio label="å¦" |
| | | :disabled="!canEditProducts" |
| | | :name="false"> |
| | | </u-radio> |
| | | </u-radio-group> |
| | |
| | | </view> |
| | | </view> |
| | | <!-- 使ç¨å
Œ
±åºé¨æé®ç»ä»¶ --> |
| | | <FooterButtons :show="operationType !== 'view'" |
| | | <FooterButtons :show="operationType !== 'view' && !isApprovalPassed" |
| | | cancelText="åæ¶" |
| | | confirmText="ä¿å" |
| | | @cancel="goBack" |
| | |
| | | getSalesNo, |
| | | approveProcessGetInfo, |
| | | } from "@/api/procurementManagement/procurementLedger"; |
| | | import { delProduct } from "@/api/salesManagement/salesLedger"; |
| | | import PageHeader from "@/components/PageHeader.vue"; |
| | | import FooterButtons from "@/components/FooterButtons.vue"; |
| | | import { userListNoPageByTenantId } from "@/api/system/user"; |
| | |
| | | const operationType = ref(""); |
| | | const editData = ref(null); |
| | | const formRef = ref(null); |
| | | // 审æ¹éè¿ï¼approvalStatus === 3ï¼åï¼ç¦æ¢ç¼è¾/å é¤äº§å |
| | | const isApprovalPassed = computed(() => { |
| | | const status = editData.value?.approvalStatus ?? form.value?.approvalStatus; |
| | | return Number(status) === 3; |
| | | }); |
| | | const canEditProducts = computed(() => { |
| | | return operationType.value !== "view" && !isApprovalPassed.value; |
| | | }); |
| | | |
| | | const userStore = useUserStore(); |
| | | const form = ref({ |
| | |
| | | })); |
| | | }); |
| | | |
| | | // 计ç®ä¾åºåéæ©å表 |
| | | // 计ç®ä¾åºåéæ©å表ï¼åªä¿ç isWhite === 0 çä¾åºåï¼ |
| | | const supplierActionList = computed(() => { |
| | | return supplierList.value.map(item => ({ |
| | | name: item.text, |
| | | value: item.value, |
| | | })); |
| | | return supplierList.value |
| | | .filter(item => item.isWhite === 0) |
| | | .map(item => ({ |
| | | name: item.text, |
| | | value: item.value, |
| | | })); |
| | | }); |
| | | |
| | | // éæ©å¨ç¸å
³åé |
| | |
| | | }; |
| | | |
| | | const addProduct = () => { |
| | | if (!canEditProducts.value) return; |
| | | if (productData.value === null) { |
| | | productData.value = []; |
| | | } |
| | |
| | | }; |
| | | |
| | | const removeProduct = idx => { |
| | | productData.value.splice(idx, 1); |
| | | if (!canEditProducts.value) return; |
| | | const row = productData.value[idx]; |
| | | |
| | | // æ°å¢æ¨¡å¼æè¿æªè½åºç产åï¼ç´æ¥å端å é¤ |
| | | if (operationType.value === "add" || !row?.id) { |
| | | productData.value.splice(idx, 1); |
| | | return; |
| | | } |
| | | |
| | | uni.showModal({ |
| | | title: "æç¤º", |
| | | content: "éä¸ç产åå°è¢«å é¤ï¼æ¯å¦ç¡®è®¤å é¤ï¼", |
| | | confirmText: "确认", |
| | | cancelText: "åæ¶", |
| | | success: res => { |
| | | if (!res.confirm) { |
| | | uni.showToast({ |
| | | title: "已忶", |
| | | icon: "none", |
| | | }); |
| | | return; |
| | | } |
| | | const ids = [row.id]; |
| | | delProduct(ids).then(() => { |
| | | uni.showToast({ |
| | | title: "å 餿å", |
| | | icon: "success", |
| | | }); |
| | | const currentId = form.value.id || editData.value?.id; |
| | | if (currentId) { |
| | | getPurchaseById({ id: currentId, type: 2 }).then(res2 => { |
| | | productData.value = res2.productData || []; |
| | | }); |
| | | } else { |
| | | // åéå¤çï¼å¦ææ²¡æå½åIDï¼åæ¬å°å é¤ |
| | | productData.value.splice(idx, 1); |
| | | } |
| | | }); |
| | | }, |
| | | }); |
| | | }; |
| | | |
| | | // æ¾ç¤ºéæ©å¨ |
| | | const openCategoryPicker = idx => { |
| | | if (!canEditProducts.value) return; |
| | | currentProductIndex.value = idx; |
| | | showCategoryPicker.value = true; |
| | | }; |
| | | |
| | | const openSpecificationPicker = idx => { |
| | | if (!canEditProducts.value) return; |
| | | currentProductIndex.value = idx; |
| | | showSpecificationPicker.value = true; |
| | | }; |
| | | |
| | | const openTaxRatePicker = idx => { |
| | | if (!canEditProducts.value) return; |
| | | currentProductIndex.value = idx; |
| | | showTaxRatePicker.value = true; |
| | | }; |
| | | |
| | | const openInvoiceTypePicker = idx => { |
| | | if (!canEditProducts.value) return; |
| | | currentProductIndex.value = idx; |
| | | showInvoiceTypePicker.value = true; |
| | | }; |
| | |
| | | supplierList.value = res.data.map(item => ({ |
| | | text: item.supplierName, |
| | | value: item.id, |
| | | isWhite: item.isWhite, |
| | | })); |
| | | }); |
| | | }; |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view class="accident-detail"> |
| | | <PageHeader :title="isEdit ? 'ç¼è¾äºæ
æ¥å' : 'æ°å¢äºæ
æ¥å'" |
| | | @back="goBack" /> |
| | | <u-form @submit="handleSubmit" |
| | | ref="formRef" |
| | | label-width="110"> |
| | | <!-- äºæ
ä¿¡æ¯ --> |
| | | <u-cell-group title="åºæ¬ä¿¡æ¯"> |
| | | <u-form-item label="äºæ
åç§°" |
| | | prop="accidentName" |
| | | required |
| | | border-bottom> |
| | | <u-input v-model="form.accidentName" |
| | | placeholder="请è¾å
¥äºæ
åç§°" /> |
| | | </u-form-item> |
| | | <u-form-item label="äºæ
ç¼ç " |
| | | prop="accidentCode" |
| | | required |
| | | border-bottom> |
| | | <u-input v-model="form.accidentCode" |
| | | placeholder="请è¾å
¥äºæ
ç¼ç " /> |
| | | </u-form-item> |
| | | <u-form-item label="äºæ
ç±»å" |
| | | prop="accidentType" |
| | | required |
| | | border-bottom> |
| | | <u-input v-model="accidentTypeName" |
| | | placeholder="è¯·éæ©äºæ
ç±»å" |
| | | @click="showTypeSheet" |
| | | readonly /> |
| | | <template #right> |
| | | <up-icon name="arrow-right" |
| | | @click="showTypeSheet"></up-icon> |
| | | </template> |
| | | </u-form-item> |
| | | <u-form-item label="äºæ
ç级" |
| | | prop="accidentGrade" |
| | | required |
| | | border-bottom> |
| | | <u-input v-model="accidentGradeName" |
| | | placeholder="è¯·éæ©äºæ
ç级" |
| | | @click="showGradeSheet" |
| | | readonly /> |
| | | <template #right> |
| | | <up-icon name="arrow-right" |
| | | @click="showGradeSheet"></up-icon> |
| | | </template> |
| | | </u-form-item> |
| | | </u-cell-group> |
| | | <u-cell-group title="详ç»ä¿¡æ¯"> |
| | | <u-form-item label="åçæ¶é´" |
| | | prop="happenTime" |
| | | required |
| | | border-bottom> |
| | | <u-input v-model="form.happenTime" |
| | | placeholder="è¯·éæ©åçæ¶é´" |
| | | @click="showTimePicker" |
| | | readonly /> |
| | | <template #right> |
| | | <up-icon name="arrow-right" |
| | | @click="showTimePicker"></up-icon> |
| | | </template> |
| | | </u-form-item> |
| | | <u-form-item label="äºæ
å°ç¹" |
| | | prop="happenLocation" |
| | | required |
| | | border-bottom> |
| | | <u-input v-model="form.happenLocation" |
| | | placeholder="请è¾å
¥äºæ
å°ç¹" /> |
| | | </u-form-item> |
| | | <u-form-item label="ç´æ¥è´¢äº§æå¤±" |
| | | prop="assetLoss" |
| | | border-bottom> |
| | | <u-input v-model="form.assetLoss" |
| | | placeholder="请è¾å
¥ç´æ¥è´¢äº§æå¤±" |
| | | type="number" /> |
| | | <template #right> |
| | | <view class="unit">å
</view> |
| | | </template> |
| | | </u-form-item> |
| | | <u-form-item label="äºæ
ç´æ¥åå " |
| | | prop="accidentCause" |
| | | border-bottom> |
| | | <u-textarea v-model="form.accidentCause" |
| | | placeholder="请è¾å
¥äºæ
ç´æ¥åå " |
| | | :maxlength="200" |
| | | count |
| | | :autoHeight="true" /> |
| | | </u-form-item> |
| | | <u-form-item label="äºæ
æ ¹æ¬åå " |
| | | prop="rootCause" |
| | | border-bottom> |
| | | <u-textarea v-model="form.rootCause" |
| | | placeholder="请è¾å
¥äºæ
æ ¹æ¬åå " |
| | | :maxlength="200" |
| | | count |
| | | :autoHeight="true" /> |
| | | </u-form-item> |
| | | <u-form-item label="ç产影åæ
åµ" |
| | | prop="productionLoss" |
| | | border-bottom> |
| | | <u-textarea v-model="form.productionLoss" |
| | | placeholder="请è¾å
¥ç产影åæ
åµ" |
| | | :maxlength="200" |
| | | count |
| | | :autoHeight="true" /> |
| | | </u-form-item> |
| | | <u-form-item label="ç°åºåºæ¥å¤ç½®æªæ½" |
| | | prop="handleMeasures" |
| | | border-bottom> |
| | | <u-textarea v-model="form.handleMeasures" |
| | | placeholder="请è¾å
¥ç°åºåºæ¥å¤ç½®æªæ½" |
| | | :maxlength="200" |
| | | count |
| | | :autoHeight="true" /> |
| | | </u-form-item> |
| | | <u-form-item label="夿³¨" |
| | | prop="remark" |
| | | border-bottom> |
| | | <u-textarea v-model="form.remark" |
| | | placeholder="请è¾å
¥å¤æ³¨" |
| | | :maxlength="200" |
| | | count |
| | | :autoHeight="true" /> |
| | | </u-form-item> |
| | | </u-cell-group> |
| | | <!-- æäº¤æé® --> |
| | | <view class="footer-btns"> |
| | | <u-button class="cancel-btn" |
| | | @click="goBack">åæ¶</u-button> |
| | | <u-button class="sign-btn" |
| | | type="primary" |
| | | @click="handleSubmit" |
| | | :loading="loading">{{ isEdit ? 'ä¿åä¿®æ¹' : 'æäº¤' }}</u-button> |
| | | </view> |
| | | </u-form> |
| | | <!-- äºæ
ç±»åéæ©å¨ --> |
| | | <up-action-sheet :show="typeSheetVisible" |
| | | :actions="typeOptions" |
| | | @select="handleTypeSelect" |
| | | @close="typeSheetVisible = false" |
| | | title="éæ©äºæ
ç±»å" /> |
| | | <!-- äºæ
ççº§éæ©å¨ --> |
| | | <up-action-sheet :show="gradeSheetVisible" |
| | | :actions="gradeOptions" |
| | | @select="handleGradeSelect" |
| | | @close="gradeSheetVisible = false" |
| | | title="éæ©äºæ
ç级" /> |
| | | <!-- æ¶é´éæ©å¨ --> |
| | | <up-datetime-picker :show="timePickerVisible" |
| | | mode="datetime" |
| | | v-model="currentTime" |
| | | @confirm="handleTimeConfirm" |
| | | @cancel="timePickerVisible = false" |
| | | title="éæ©åçæ¶é´" /> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | // æ¿æ¢ toast æ¹æ³ |
| | | defineOptions({ name: "accident-detail" }); |
| | | const showToast = message => { |
| | | uni.showToast({ title: message, icon: "none" }); |
| | | }; |
| | | |
| | | import { ref, onMounted } from "vue"; |
| | | import PageHeader from "@/components/PageHeader.vue"; |
| | | import { |
| | | safeAccidentAdd, |
| | | safeAccidentUpdate, |
| | | } from "@/api/safeProduction/accidentReportingRecord"; |
| | | import { onLoad } from "@dcloudio/uni-app"; |
| | | import { useDict } from "@/utils/dict"; |
| | | import dayjs from "dayjs"; |
| | | |
| | | // è·ååå
¸æ°æ® |
| | | const { accident_type } = useDict("accident_type"); |
| | | |
| | | // è¡¨åæ°æ® |
| | | const form = ref({ |
| | | accidentName: "", |
| | | accidentCode: "", |
| | | accidentType: "", |
| | | accidentGrade: "", |
| | | happenTime: "", |
| | | happenLocation: "", |
| | | createUserName: "", |
| | | createTime: "", |
| | | assetLoss: "", |
| | | accidentCause: "", |
| | | rootCause: "", |
| | | productionLoss: "", |
| | | handleMeasures: "", |
| | | remark: "", |
| | | }); |
| | | |
| | | // 页é¢ç¶æ |
| | | const loading = ref(false); |
| | | const formRef = ref(null); |
| | | const isEdit = ref(false); |
| | | const currentTime = ref(new Date()); |
| | | |
| | | // äºæ
ç±»åéæ©å¨ |
| | | const typeSheetVisible = ref(false); |
| | | const accidentTypeName = ref(""); |
| | | const typeOptions = ref([]); |
| | | |
| | | const showTypeSheet = () => { |
| | | typeSheetVisible.value = true; |
| | | }; |
| | | |
| | | const handleTypeSelect = item => { |
| | | form.value.accidentType = item.value; |
| | | accidentTypeName.value = item.name; |
| | | typeSheetVisible.value = false; |
| | | }; |
| | | |
| | | // äºæ
ççº§éæ©å¨ |
| | | const gradeSheetVisible = ref(false); |
| | | const accidentGradeName = ref(""); |
| | | const gradeOptions = ref([ |
| | | { value: "è½»å¾®äºæ
", name: "è½»å¾®äºæ
" }, |
| | | { value: "ä¸è¬äºæ
", name: "ä¸è¬äºæ
" }, |
| | | { value: "è¾å¤§äºæ
", name: "è¾å¤§äºæ
" }, |
| | | { value: "éå¤§äºæ
", name: "éå¤§äºæ
" }, |
| | | ]); |
| | | |
| | | const showGradeSheet = () => { |
| | | gradeSheetVisible.value = true; |
| | | }; |
| | | |
| | | const handleGradeSelect = item => { |
| | | form.value.accidentGrade = item.value; |
| | | accidentGradeName.value = item.name; |
| | | gradeSheetVisible.value = false; |
| | | }; |
| | | |
| | | // æ¶é´éæ©å¨ |
| | | const timePickerVisible = ref(false); |
| | | |
| | | const showTimePicker = () => { |
| | | timePickerVisible.value = true; |
| | | }; |
| | | |
| | | const handleTimeConfirm = e => { |
| | | form.value.happenTime = dayjs(e.value).format("YYYY-MM-DD HH:mm:ss"); |
| | | currentTime.value = e.value; |
| | | timePickerVisible.value = false; |
| | | }; |
| | | |
| | | // è¿åä¸ä¸é¡µ |
| | | const goBack = () => { |
| | | uni.removeStorageSync("accidentReport"); |
| | | uni.navigateBack(); |
| | | }; |
| | | |
| | | // æäº¤è¡¨å |
| | | const handleSubmit = async () => { |
| | | if (!form.value.accidentName) { |
| | | showToast("请è¾å
¥äºæ
åç§°"); |
| | | return; |
| | | } |
| | | |
| | | if (!form.value.accidentCode) { |
| | | showToast("请è¾å
¥äºæ
ç¼ç "); |
| | | return; |
| | | } |
| | | |
| | | if (!form.value.accidentType) { |
| | | showToast("è¯·éæ©äºæ
ç±»å"); |
| | | return; |
| | | } |
| | | |
| | | if (!form.value.accidentGrade) { |
| | | showToast("è¯·éæ©äºæ
ç级"); |
| | | return; |
| | | } |
| | | |
| | | if (!form.value.happenTime) { |
| | | showToast("è¯·éæ©åçæ¶é´"); |
| | | return; |
| | | } |
| | | |
| | | if (!form.value.happenLocation) { |
| | | showToast("请è¾å
¥äºæ
å°ç¹"); |
| | | return; |
| | | } |
| | | |
| | | try { |
| | | loading.value = true; |
| | | |
| | | // 使ç¨å®å
¨æµ
æ·è´ |
| | | const source = |
| | | form.value && typeof form.value === "object" ? form.value : {}; |
| | | const submitData = {}; |
| | | Object.keys(source).forEach(k => { |
| | | submitData[k] = source[k]; |
| | | }); |
| | | |
| | | if (isEdit.value) { |
| | | const { code } = await safeAccidentUpdate(submitData); |
| | | if (code === 200) { |
| | | showToast("ä¿®æ¹æå"); |
| | | setTimeout(() => { |
| | | goBack(); |
| | | }, 500); |
| | | } else { |
| | | loading.value = false; |
| | | showToast("ä¿®æ¹å¤±è´¥ï¼è¯·éè¯"); |
| | | } |
| | | } else { |
| | | const { code } = await safeAccidentAdd(submitData); |
| | | if (code === 200) { |
| | | showToast("æ°å¢æå"); |
| | | setTimeout(() => { |
| | | goBack(); |
| | | }, 500); |
| | | } else { |
| | | loading.value = false; |
| | | showToast("æ°å¢å¤±è´¥ï¼è¯·éè¯"); |
| | | } |
| | | } |
| | | } catch (e) { |
| | | loading.value = false; |
| | | console.error("æäº¤å¤±è´¥:", e); |
| | | showToast("æäº¤å¤±è´¥ï¼è¯·éè¯"); |
| | | } |
| | | }; |
| | | |
| | | onLoad(() => { |
| | | // ç¼è¾äºæ
æ¶ï¼ä»æ¬å°åå¨è·åæ°æ® |
| | | const accidentReport = uni.getStorageSync("accidentReport"); |
| | | if (accidentReport.id) { |
| | | form.value = accidentReport; |
| | | currentTime.value = dayjs(accidentReport.happenTime).toDate(); |
| | | isEdit.value = true; |
| | | } else { |
| | | isEdit.value = false; |
| | | } |
| | | }); |
| | | |
| | | onMounted(() => { |
| | | // åå§åäºæ
ç±»åé项 |
| | | typeOptions.value = |
| | | accident_type?.value.map(item => ({ |
| | | value: item.value, |
| | | name: item.label, |
| | | })) || []; |
| | | |
| | | // 设置已éå¼çæ¾ç¤ºææ¬ |
| | | if (form.value.accidentType) { |
| | | const typeItem = typeOptions.value.find( |
| | | item => String(item.value) === String(form.value.accidentType) |
| | | ); |
| | | accidentTypeName.value = typeItem ? typeItem.name : ""; |
| | | } |
| | | if (form.value.accidentGrade) { |
| | | const gradeItem = gradeOptions.value.find( |
| | | item => item.value === form.value.accidentGrade |
| | | ); |
| | | accidentGradeName.value = gradeItem ? gradeItem.name : ""; |
| | | } |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | @import "@/static/scss/form-common.scss"; |
| | | |
| | | .accident-detail { |
| | | min-height: 100vh; |
| | | background: #f8f9fa; |
| | | padding-bottom: 5rem; |
| | | } |
| | | |
| | | .footer-btns { |
| | | position: fixed; |
| | | left: 0; |
| | | right: 0; |
| | | bottom: 0; |
| | | background: #fff; |
| | | display: flex; |
| | | justify-content: space-around; |
| | | align-items: center; |
| | | padding: 0.75rem 0; |
| | | box-shadow: 0 -0.125rem 0.5rem rgba(0, 0, 0, 0.05); |
| | | z-index: 1000; |
| | | } |
| | | |
| | | .cancel-btn { |
| | | font-weight: 400; |
| | | font-size: 1rem; |
| | | color: #666; |
| | | background: #f5f5f5; |
| | | border: 1px solid #ddd; |
| | | width: 45%; |
| | | height: 2.5rem; |
| | | border-radius: 2.5rem; |
| | | } |
| | | |
| | | .sign-btn { |
| | | font-weight: 500; |
| | | font-size: 1rem; |
| | | color: #fff; |
| | | background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); |
| | | border: none; |
| | | width: 45%; |
| | | height: 2.5rem; |
| | | border-radius: 2.5rem; |
| | | } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view class="accident-report"> |
| | | <!-- 使ç¨éç¨é¡µé¢å¤´é¨ç»ä»¶ --> |
| | | <PageHeader title="äºæ
䏿¥è®°å½" |
| | | @back="goBack" /> |
| | | <!-- æç´¢åºå --> |
| | | <view class="search-section"> |
| | | <view class="search-bar"> |
| | | <view class="search-input"> |
| | | <up-input class="search-text" |
| | | placeholder="请è¾å
¥äºæ
åç§°" |
| | | v-model="accidentName" |
| | | @change="searchChange" |
| | | clearable /> |
| | | </view> |
| | | <view class="filter-button" |
| | | @click="getList"> |
| | | <u-icon name="search" |
| | | size="24" |
| | | color="#999"></u-icon> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <!-- äºæ
è®°å½å表 --> |
| | | <view class="ledger-list" |
| | | v-if="accidentList.length > 0"> |
| | | <view v-for="(item, index) in accidentList" |
| | | :key="index"> |
| | | <view class="ledger-item"> |
| | | <!-- <view class="item-header"> |
| | | <view class="item-left"> |
| | | <view class="document-icon"> |
| | | <up-icon name="file-text" |
| | | size="16" |
| | | color="#ffffff"></up-icon> |
| | | </view> |
| | | <text class="item-id">äºæ
åç§°ï¼{{ item.accidentName }}</text> |
| | | </view> |
| | | </view> --> |
| | | <view class="item-header"> |
| | | <view class="item-left"> |
| | | <view class="document-icon"> |
| | | <up-icon name="file-text" |
| | | size="16" |
| | | color="#ffffff"></up-icon> |
| | | </view> |
| | | <text class="item-title">äºæ
åç§°ï¼{{ item.accidentName }}</text> |
| | | </view> |
| | | </view> |
| | | <up-divider></up-divider> |
| | | <view class="item-details"> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">äºæ
ç¼ç </text> |
| | | <text class="detail-value">{{ item.accidentCode || '-' }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">äºæ
ç±»å</text> |
| | | <text class="detail-value">{{ accidentTypeLabel(item.accidentType) || '-' }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">åçæ¶é´</text> |
| | | <text class="detail-value">{{ item.happenTime || '-' }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">äºæ
å°ç¹</text> |
| | | <text class="detail-value">{{ item.happenLocation || '-' }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">äºæ
ç级</text> |
| | | <u-tag :type="accidentGradeType(item.accidentGrade)"> |
| | | {{ item.accidentGrade || '-' }} |
| | | </u-tag> |
| | | </view> |
| | | </view> |
| | | <!-- æé®åºå --> |
| | | <view class="action-buttons"> |
| | | <u-button type="info" |
| | | size="small" |
| | | class="action-btn" |
| | | @click="viewDetail(item)"> |
| | | æ¥ç详æ
|
| | | </u-button> |
| | | <u-button type="primary" |
| | | size="small" |
| | | class="action-btn" |
| | | @click="editAccident(item)"> |
| | | ç¼è¾ |
| | | </u-button> |
| | | <u-button type="error" |
| | | size="small" |
| | | class="action-btn" |
| | | @click="deleteAccident(item)"> |
| | | å é¤ |
| | | </u-button> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <view v-else |
| | | class="no-data"> |
| | | <text>ææ äºæ
è®°å½</text> |
| | | </view> |
| | | <!-- æµ®å¨æ°å¢æé® --> |
| | | <view class="fab-button" |
| | | @click="addAccident"> |
| | | <up-icon name="plus" |
| | | size="24" |
| | | color="#ffffff"></up-icon> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, onMounted, computed } from "vue"; |
| | | import { onShow } from "@dcloudio/uni-app"; |
| | | import PageHeader from "@/components/PageHeader.vue"; |
| | | import { |
| | | safeAccidentListPage, |
| | | safeAccidentDel, |
| | | } from "@/api/safeProduction/accidentReportingRecord"; |
| | | import { useDict } from "@/utils/dict"; |
| | | |
| | | // æ¿æ¢ toast æ¹æ³ |
| | | defineOptions({ name: "accident-report-index" }); |
| | | const showToast = message => { |
| | | uni.showToast({ |
| | | title: message, |
| | | icon: "none", |
| | | }); |
| | | }; |
| | | // åºæ¥é¢æ¡ç±»åé项 |
| | | const { accident_type } = useDict("accident_type"); |
| | | const emergencyPlanTypeOptions = computed(() => accident_type?.value || []); |
| | | |
| | | // æç´¢å
³é®è¯ |
| | | const accidentName = ref(""); |
| | | |
| | | // äºæ
è®°å½æ°æ® |
| | | const accidentList = ref([]); |
| | | |
| | | // è¿åä¸ä¸é¡µ |
| | | const goBack = () => { |
| | | uni.navigateBack(); |
| | | }; |
| | | |
| | | const accidentGradeType = val => { |
| | | switch (val) { |
| | | case "è½»å¾®äºæ
": |
| | | return "info"; |
| | | case "ä¸è¬äºæ
": |
| | | return "info"; |
| | | case "è¾å¤§äºæ
": |
| | | return "warning"; |
| | | case "éå¤§äºæ
": |
| | | return "error"; |
| | | default: |
| | | return "info"; |
| | | } |
| | | }; |
| | | const accidentGradeOptions = [ |
| | | { |
| | | label: "è½»å¾®äºæ
", |
| | | value: "è½»å¾®äºæ
", |
| | | }, |
| | | { |
| | | label: "ä¸è¬äºæ
", |
| | | value: "ä¸è¬äºæ
", |
| | | }, |
| | | { |
| | | label: "è¾å¤§äºæ
", |
| | | value: "è¾å¤§äºæ
", |
| | | }, |
| | | { |
| | | label: "éå¤§äºæ
", |
| | | value: "éå¤§äºæ
", |
| | | }, |
| | | ]; |
| | | // è·åäºæ
ç±»åæ ç¾ |
| | | const accidentTypeLabel = val => { |
| | | const item = emergencyPlanTypeOptions.value.find( |
| | | i => String(i.value) === String(val) |
| | | ); |
| | | return item ? item.label : val; |
| | | }; |
| | | const searchChange = val => { |
| | | accidentName.value = val; |
| | | getList(); |
| | | }; |
| | | |
| | | // æ¥è¯¢å表 |
| | | const getList = () => { |
| | | showLoadingToast("å è½½ä¸..."); |
| | | const params = { |
| | | current: -1, |
| | | size: -1, |
| | | accidentName: accidentName.value, |
| | | }; |
| | | safeAccidentListPage(params) |
| | | .then(res => { |
| | | accidentList.value = res.records || res.data?.records || []; |
| | | closeToast(); |
| | | }) |
| | | .catch(() => { |
| | | closeToast(); |
| | | showToast("è·åæ°æ®å¤±è´¥"); |
| | | }); |
| | | }; |
| | | |
| | | // æ¾ç¤ºå è½½æç¤º |
| | | const showLoadingToast = message => { |
| | | uni.showLoading({ |
| | | title: message, |
| | | mask: true, |
| | | }); |
| | | }; |
| | | |
| | | // å
³éæç¤º |
| | | const closeToast = () => { |
| | | uni.hideLoading(); |
| | | }; |
| | | |
| | | // æ°å¢äºæ
è®°å½ |
| | | const addAccident = () => { |
| | | uni.setStorageSync("accidentReport", {}); |
| | | uni.navigateTo({ |
| | | url: "/pages/safeProduction/accidentReportingRecord/detail", |
| | | }); |
| | | }; |
| | | |
| | | // ç¼è¾äºæ
è®°å½ |
| | | const editAccident = item => { |
| | | uni.setStorageSync("accidentReport", item); |
| | | uni.navigateTo({ |
| | | url: "/pages/safeProduction/accidentReportingRecord/detail", |
| | | }); |
| | | }; |
| | | |
| | | // å é¤äºæ
è®°å½ |
| | | const deleteAccident = item => { |
| | | uni.showModal({ |
| | | title: "å é¤ç¡®è®¤", |
| | | content: `ç¡®å®è¦å é¤è¯¥äºæ
è®°å½åï¼`, |
| | | success: res => { |
| | | if (res.confirm) { |
| | | deleteAccidentRecord(item.id); |
| | | } |
| | | }, |
| | | }); |
| | | }; |
| | | |
| | | // å é¤äºæ
è®°å½ |
| | | const deleteAccidentRecord = id => { |
| | | showLoadingToast("å é¤ä¸..."); |
| | | safeAccidentDel([id]) |
| | | .then(() => { |
| | | closeToast(); |
| | | showToast("å 餿å"); |
| | | getList(); |
| | | }) |
| | | .catch(() => { |
| | | closeToast(); |
| | | showToast("å é¤å¤±è´¥"); |
| | | }); |
| | | }; |
| | | |
| | | // æ¥ç详æ
|
| | | const viewDetail = item => { |
| | | uni.setStorageSync("accidentReport", item); |
| | | uni.navigateTo({ |
| | | url: "/pages/safeProduction/accidentReportingRecord/view", |
| | | }); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getList(); |
| | | }); |
| | | |
| | | onShow(() => { |
| | | getList(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | @import "../../../styles/sales-common.scss"; |
| | | |
| | | // 页é¢ç¹å®çæ ·å¼è¦ç |
| | | .accident-report { |
| | | min-height: 100vh; |
| | | background: #f8f9fa; |
| | | position: relative; |
| | | padding-bottom: 80px; |
| | | } |
| | | |
| | | // ç¹å®ç徿 æ ·å¼ |
| | | .document-icon { |
| | | background: #667eea; // ä¿æé¡µé¢ç¹æçèæ¯è² |
| | | } |
| | | |
| | | // ç¹ææ ·å¼ |
| | | .visit-status { |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | |
| | | .detail-value { |
| | | word-break: break-all; // ä¿ç页é¢ç¹æçææ¬æ¢è¡æ ·å¼ |
| | | white-space: normal; |
| | | line-height: 1.4; |
| | | } |
| | | |
| | | // ç¹å®çæµ®å¨æé®æ ·å¼ |
| | | .fab-button { |
| | | background: #667eea; // ä¿æé¡µé¢ç¹æçèæ¯è² |
| | | box-shadow: 0 4px 16px rgba(102, 126, 234, 0.3); // ä¿æé¡µé¢ç¹æçé´å½±ææ |
| | | } |
| | | .action-buttons { |
| | | gap: 4px; |
| | | } |
| | | .action-buttons { |
| | | padding: 0 0 10rpx 0; |
| | | } |
| | | |
| | | // è¶
ææªæ´æ¹çéæ£æ ·å¼ |
| | | .overdue { |
| | | border-left: 8rpx solid #ff4d4f; |
| | | background-color: rgba(255, 77, 79, 0.02); |
| | | } |
| | | |
| | | .overdue .item-header { |
| | | position: relative; |
| | | padding-left: 20rpx; |
| | | } |
| | | |
| | | .overdue .item-header::after { |
| | | content: "è¶
æ"; |
| | | position: absolute; |
| | | top: 32rpx; |
| | | right: 20rpx; |
| | | font-size: 24rpx; |
| | | font-weight: 500; |
| | | color: #ff4d4f; |
| | | background-color: rgba(255, 77, 79, 0.1); |
| | | padding: 4rpx 16rpx; |
| | | border-radius: 16rpx; |
| | | border: 1rpx solid rgba(255, 77, 79, 0.3); |
| | | } |
| | | |
| | | .overdue .detail-row:nth-child(7) .detail-value { |
| | | color: #ff4d4f; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | .overdue .detail-row { |
| | | padding-left: 20rpx; |
| | | } |
| | | </style> |
| | | |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view class="accident-view"> |
| | | <PageHeader title="äºæ
æ¥å详æ
" |
| | | @back="goBack" /> |
| | | <view class="detail-container"> |
| | | <!-- äºæ
åºæ¬ä¿¡æ¯ --> |
| | | <view class="info-section"> |
| | | <view class="info-title">åºæ¬ä¿¡æ¯</view> |
| | | <view class="info-content"> |
| | | <view class="info-row"> |
| | | <view class="info-label">äºæ
åç§°ï¼</view> |
| | | <view class="info-value">{{ accidentInfo.accidentName || '-' }}</view> |
| | | </view> |
| | | <view class="info-row"> |
| | | <view class="info-label">äºæ
ç¼ç ï¼</view> |
| | | <view class="info-value">{{ accidentInfo.accidentCode || '-' }}</view> |
| | | </view> |
| | | <view class="info-row"> |
| | | <view class="info-label">äºæ
ç±»åï¼</view> |
| | | <view class="info-value">{{ accidentTypeLabel(accidentInfo.accidentType) || '-' }}</view> |
| | | </view> |
| | | <view class="info-row"> |
| | | <view class="info-label">äºæ
ç级ï¼</view> |
| | | <view class="info-value"> |
| | | <u-tag :type="getAccidentLevelType(accidentInfo.accidentGrade)"> |
| | | {{ accidentInfo.accidentGrade || '-' }} |
| | | </u-tag> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <!-- äºæ
详ç»ä¿¡æ¯ --> |
| | | <view class="info-section"> |
| | | <view class="info-title">详ç»ä¿¡æ¯</view> |
| | | <view class="info-content"> |
| | | <view class="info-row"> |
| | | <view class="info-label">åçæ¶é´ï¼</view> |
| | | <view class="info-value">{{ accidentInfo.happenTime || '-' }}</view> |
| | | </view> |
| | | <view class="info-row"> |
| | | <view class="info-label">äºæ
å°ç¹ï¼</view> |
| | | <view class="info-value">{{ accidentInfo.happenLocation || '-' }}</view> |
| | | </view> |
| | | <view class="info-row"> |
| | | <view class="info-label">䏿¥äººï¼</view> |
| | | <view class="info-value">{{ accidentInfo.createUserName || '-' }}</view> |
| | | </view> |
| | | <view class="info-row"> |
| | | <view class="info-label">䏿¥æ¶é´ï¼</view> |
| | | <view class="info-value">{{ accidentInfo.createTime || '-' }}</view> |
| | | </view> |
| | | <view class="info-row"> |
| | | <view class="info-label">ç´æ¥è´¢äº§æå¤±ï¼</view> |
| | | <view class="info-value">{{ accidentInfo.assetLoss || '-' }}<span v-if="accidentInfo.assetLoss">å
</span></view> |
| | | </view> |
| | | <view class="info-row"> |
| | | <view class="info-label">䏿¥æ¶é´ï¼</view> |
| | | <view class="info-value">{{ accidentInfo.createTime || '-' }}</view> |
| | | </view> |
| | | <view class="info-row"> |
| | | <view class="info-label">äºæ
ç´æ¥åå ï¼</view> |
| | | <view class="info-value">{{ accidentInfo.accidentCause || '-' }}</view> |
| | | </view> |
| | | <view class="info-row"> |
| | | <view class="info-label">äºæ
æ ¹æ¬åå ï¼</view> |
| | | <view class="info-value">{{ accidentInfo.rootCause || '-' }}</view> |
| | | </view> |
| | | <view class="info-row"> |
| | | <view class="info-label">ç产影åæ
åµï¼</view> |
| | | <view class="info-value">{{ accidentInfo.productionLoss || '-' }}</view> |
| | | </view> |
| | | <view class="info-row"> |
| | | <view class="info-label">ç°åºåºæ¥å¤ç½®æªæ½ï¼</view> |
| | | <view class="info-value">{{ accidentInfo.handleMeasures || '-' }}</view> |
| | | </view> |
| | | <view class="info-row"> |
| | | <view class="info-label">夿³¨ï¼</view> |
| | | <view class="info-value">{{ accidentInfo.remark || '-' }}</view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <!-- äºæ
æè¿° --> |
| | | <view class="info-section" |
| | | v-if="accidentInfo.accidentDescription"> |
| | | <view class="info-title">äºæ
æè¿°</view> |
| | | <view class="description-content"> |
| | | {{ accidentInfo.accidentDescription }} |
| | | </view> |
| | | </view> |
| | | <!-- å¤çæªæ½ --> |
| | | <view class="info-section" |
| | | v-if="accidentInfo.handlingMeasures"> |
| | | <view class="info-title">å¤çæªæ½</view> |
| | | <view class="description-content"> |
| | | {{ accidentInfo.handlingMeasures }} |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, onMounted, computed } from "vue"; |
| | | import PageHeader from "@/components/PageHeader.vue"; |
| | | import { onLoad } from "@dcloudio/uni-app"; |
| | | import { useDict } from "@/utils/dict"; |
| | | // åºæ¥é¢æ¡ç±»åé项 |
| | | const { accident_type } = useDict("accident_type"); |
| | | const emergencyPlanTypeOptions = computed(() => accident_type?.value || []); |
| | | |
| | | // è·åäºæ
ç±»åæ ç¾ |
| | | const accidentTypeLabel = val => { |
| | | const item = emergencyPlanTypeOptions.value.find( |
| | | i => String(i.value) === String(val) |
| | | ); |
| | | return item ? item.label : val; |
| | | }; |
| | | |
| | | // æ¿æ¢ toast æ¹æ³ |
| | | defineOptions({ name: "accident-view" }); |
| | | const showToast = message => { |
| | | uni.showToast({ title: message, icon: "none" }); |
| | | }; |
| | | |
| | | // äºæ
ä¿¡æ¯ |
| | | const accidentInfo = ref({}); |
| | | |
| | | // è¿åä¸ä¸é¡µ |
| | | const goBack = () => { |
| | | uni.navigateBack(); |
| | | }; |
| | | |
| | | // è·åäºæ
ç级æ ç¾ç±»å |
| | | const getAccidentLevelType = val => { |
| | | switch (val) { |
| | | case "è½»å¾®äºæ
": |
| | | return "info"; |
| | | case "ä¸è¬äºæ
": |
| | | return "info"; |
| | | case "è¾å¤§äºæ
": |
| | | return "warning"; |
| | | case "éå¤§äºæ
": |
| | | return "error"; |
| | | default: |
| | | return "info"; |
| | | } |
| | | }; |
| | | |
| | | onLoad(() => { |
| | | // 仿¬å°åå¨è·åäºæ
ä¿¡æ¯ |
| | | const accidentReport = uni.getStorageSync("accidentReport"); |
| | | if (accidentReport) { |
| | | accidentInfo.value = accidentReport; |
| | | } |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | @import "@/static/scss/form-common.scss"; |
| | | |
| | | .accident-view { |
| | | min-height: 100vh; |
| | | background: #f8f9fa; |
| | | padding-bottom: 2rem; |
| | | } |
| | | |
| | | .detail-container { |
| | | padding: 1rem; |
| | | } |
| | | |
| | | .info-section { |
| | | background: #fff; |
| | | border-radius: 0.5rem; |
| | | margin-bottom: 1rem; |
| | | box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.05); |
| | | overflow: hidden; |
| | | } |
| | | |
| | | .info-title { |
| | | padding: 1rem; |
| | | font-size: 1rem; |
| | | font-weight: 500; |
| | | color: #303133; |
| | | background: #f5f5f5; |
| | | border-bottom: 1px solid #e4e7ed; |
| | | } |
| | | |
| | | .info-content { |
| | | padding: 1rem; |
| | | } |
| | | |
| | | .info-row { |
| | | display: flex; |
| | | margin-bottom: 0.75rem; |
| | | align-items: flex-start; |
| | | } |
| | | |
| | | .info-row:last-child { |
| | | margin-bottom: 0; |
| | | } |
| | | |
| | | .info-label { |
| | | width: 240rpx; |
| | | font-size: 0.875rem; |
| | | color: #606266; |
| | | } |
| | | |
| | | .info-value { |
| | | flex: 1; |
| | | font-size: 0.875rem; |
| | | color: #303133; |
| | | word-break: break-all; |
| | | white-space: normal; |
| | | line-height: 1.4; |
| | | } |
| | | |
| | | .description-content { |
| | | padding: 1rem; |
| | | font-size: 0.875rem; |
| | | color: #303133; |
| | | line-height: 1.5; |
| | | } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view class="emergency-plan-detail"> |
| | | <!-- 使ç¨éç¨é¡µé¢å¤´é¨ç»ä»¶ --> |
| | | <PageHeader :title="isEdit ? 'ç¼è¾åºæ¥é¢æ¡' : 'æ°å¢åºæ¥é¢æ¡'" |
| | | @back="goBack" /> |
| | | <!-- 表ååºå --> |
| | | <u-form :model="form" |
| | | label-width="110" |
| | | :rules="rules" |
| | | ref="formRef"> |
| | | <!-- åºæ¥é¢æ¡ç¼ç --> |
| | | <u-form-item label="åºæ¥é¢æ¡ç¼ç " |
| | | border-bottom |
| | | required |
| | | prop="planCode"> |
| | | <up-input v-model="form.planCode" |
| | | placeholder="请è¾å
¥åºæ¥é¢æ¡ç¼ç " |
| | | clearable /> |
| | | </u-form-item> |
| | | <!-- åºæ¥é¢æ¡åç§° --> |
| | | <u-form-item label="åºæ¥é¢æ¡åç§°" |
| | | required |
| | | border-bottom |
| | | prop="planName"> |
| | | <up-input v-model="form.planName" |
| | | placeholder="请è¾å
¥åºæ¥é¢æ¡åç§°" |
| | | clearable /> |
| | | </u-form-item> |
| | | <!-- åå¸çææ¶é´ --> |
| | | <u-form-item label="åå¸çææ¶é´" |
| | | required |
| | | border-bottom |
| | | prop="publishTime"> |
| | | <up-input v-model="form.publishTime" |
| | | placeholder="è¯·éæ©åå¸çææ¶é´" |
| | | readonly |
| | | @click="showTime = true" /> |
| | | <template #right> |
| | | <up-icon name="arrow-right" |
| | | @click="showTime = true"></up-icon> |
| | | </template> |
| | | </u-form-item> |
| | | <!-- 颿¡ç±»å --> |
| | | <u-form-item label="颿¡ç±»å" |
| | | prop="planType" |
| | | required |
| | | border-bottom> |
| | | <u-input v-model="emergencyPlanTypeLabel" |
| | | placeholder="è¯·éæ©é¢æ¡ç±»å" |
| | | @click="showPlanTypeActionSheet = true" |
| | | readonly /> |
| | | <template #right> |
| | | <up-icon name="arrow-right" |
| | | @click="showPlanTypeActionSheet = true"></up-icon> |
| | | </template> |
| | | </u-form-item> |
| | | <u-form-item label="æ ¸å¿è´£ä»»äºº" |
| | | prop="coreResponsorUserId" |
| | | required |
| | | border-bottom> |
| | | <u-input v-model="form.coreResponsorUserName" |
| | | placeholder="è¯·éæ©æ ¸å¿è´£ä»»äºº" |
| | | @click="showUserActionSheet = true" |
| | | readonly /> |
| | | <template #right> |
| | | <up-icon name="arrow-right" |
| | | @click="showUserActionSheet = true"></up-icon> |
| | | </template> |
| | | </u-form-item> |
| | | <!-- 夿³¨ --> |
| | | <u-form-item label="夿³¨" |
| | | prop="remark"> |
| | | <up-input v-model="form.remark" |
| | | placeholder="请è¾å
¥å¤æ³¨" |
| | | type="textarea" |
| | | rows="3" |
| | | clearable /> |
| | | </u-form-item> |
| | | <!-- éç¨èå´ --> |
| | | <u-form-item label="éç¨èå´" |
| | | required |
| | | prop="applyScope"> |
| | | <view class="checkbox-group"> |
| | | <u-checkbox-group v-model="form.applyScope" |
| | | @change="handleApplyScopeChange"> |
| | | <u-checkbox shape="circle" |
| | | size="32rpx" |
| | | class="checkbox-item" |
| | | v-for="(item, index) in applyScopeOptions" |
| | | :key="index" |
| | | :label="item.label" |
| | | :name="item.value"> |
| | | </u-checkbox> |
| | | </u-checkbox-group> |
| | | </view> |
| | | </u-form-item> |
| | | <!-- åºæ¥å¤ç½®æ¥éª¤ --> |
| | | <view class="exec-steps-container"> |
| | | <view class="steps-header"> |
| | | <text class="steps-title">å¤ç½®æ¥éª¤å表</text> |
| | | <text class="steps-count">å
± {{ execStepsList.length }} 个æ¥éª¤</text> |
| | | </view> |
| | | <view class="steps-list"> |
| | | <view v-for="(step, index) in execStepsList" |
| | | :key="index" |
| | | class="exec-step-item"> |
| | | <view class="delete-btn" |
| | | @click="removeExecStep(index)"> |
| | | <u-icon name="close" |
| | | color="#fff" |
| | | size="16" /> |
| | | </view> |
| | | <view class="step-number"> |
| | | {{ index + 1 }} |
| | | </view> |
| | | <view class="step-content"> |
| | | <view class="step-row"> |
| | | <text class="step-label">æ¥éª¤åç§°ï¼</text> |
| | | <u-textarea v-model="step.step" |
| | | placeholder="请è¾å
¥æ¥éª¤åç§°" |
| | | clearable |
| | | border-bottom |
| | | class="step-input" /> |
| | | </view> |
| | | <view class="step-row"> |
| | | <text class="step-label">å¤ç½®æªæ½ï¼</text> |
| | | <u-textarea v-model="step.description" |
| | | placeholder="请è¾å
¥å
·ä½çåºæ¥å¤ç½®æªæ½" |
| | | type="textarea" |
| | | clearable |
| | | class="step-textarea" /> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <u-button type="primary" |
| | | @click="addExecStep" |
| | | class="add-step-btn"> |
| | | <text>æ·»å æ¥éª¤</text> |
| | | </u-button> |
| | | </view> |
| | | </u-form> |
| | | <!-- åå¸çææ¶é´éæ©å¨ --> |
| | | <up-datetime-picker :show="showTime" |
| | | v-model="currentTime" |
| | | @confirm="handleDateConfirm" |
| | | @cancel="showTime = false" |
| | | mode="date" /> |
| | | <!--颿¡ç±»åéæ©å¨ --> |
| | | <up-action-sheet :show="showPlanTypeActionSheet" |
| | | :actions="emergencyPlanTypeOptions" |
| | | @select="handlePlanTypeConfirm" |
| | | title="鿩颿¡ç±»å" /> |
| | | <!--æ ¸å¿è´£ä»»äººéæ©å¨ --> |
| | | <up-action-sheet :show="showUserActionSheet" |
| | | :actions="userList" |
| | | @select="handleUserConfirm" |
| | | title="éæ©æ ¸å¿è´£ä»»äºº" /> |
| | | </view> |
| | | <!-- åºé¨æé® --> |
| | | <view class="bottom-buttons"> |
| | | <u-button type="default" |
| | | size="default" |
| | | @click="goBack" |
| | | class="bottom-btn"> |
| | | åæ¶ |
| | | </u-button> |
| | | <u-button type="primary" |
| | | size="default" |
| | | @click="submitForm" |
| | | class="bottom-btn"> |
| | | ä¿å |
| | | </u-button> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, onMounted, computed } from "vue"; |
| | | import { onShow } from "@dcloudio/uni-app"; |
| | | import PageHeader from "@/components/PageHeader.vue"; |
| | | import { |
| | | safeContingencyPlanAdd, |
| | | safeContingencyPlanUpdate, |
| | | } from "@/api/safeProduction/emergencyPlanReview"; |
| | | import { userListNoPage } from "@/api/system/user"; |
| | | import { useDict } from "@/utils/dict"; |
| | | import dayjs from "dayjs"; |
| | | // æ¿æ¢ toast æ¹æ³ |
| | | defineOptions({ name: "emergency-plan-detail" }); |
| | | const showToast = message => { |
| | | uni.showToast({ |
| | | title: message, |
| | | icon: "none", |
| | | }); |
| | | }; |
| | | |
| | | // 表åå¼ç¨ |
| | | const formRef = ref(); |
| | | |
| | | // è¡¨åæ°æ® |
| | | const form = ref({ |
| | | id: "", |
| | | planCode: "", |
| | | planName: "", |
| | | publishTime: "", |
| | | planType: "", |
| | | coreResponsorUserId: "", |
| | | coreResponsorUserName: "", |
| | | remark: "", |
| | | applyScope: [], |
| | | execSteps: "", |
| | | }); |
| | | |
| | | // åºæ¥å¤ç½®æ¥éª¤å表 |
| | | const execStepsList = ref([]); |
| | | |
| | | // æ¥æèå´ |
| | | const minDate = new Date("2000-01-01"); |
| | | const maxDate = new Date("2030-12-31"); |
| | | const currentTime = ref(Date.now()); |
| | | // ç¨æ·å表 |
| | | const userList = ref([]); |
| | | |
| | | // åºæ¥é¢æ¡ç±»åé项 |
| | | const { emergency_plan_type } = useDict("emergency_plan_type"); |
| | | const emergencyPlanTypeOptions = computed(() => { |
| | | return ( |
| | | emergency_plan_type?.value.map(item => ({ |
| | | value: item.value, |
| | | name: item.label, |
| | | })) || [] |
| | | ); |
| | | }); |
| | | |
| | | // åºæ¥é¢æ¡ç±»åæ ç¾ |
| | | const emergencyPlanTypeLabel = ref(""); |
| | | |
| | | // éç¨èå´é项 |
| | | const applyScopeOptions = [ |
| | | { value: "all", label: "å
¨ä½åå·¥" }, |
| | | { value: "manager", label: "管çå±" }, |
| | | { value: "hr", label: "人äºé¨é¨" }, |
| | | { value: "finance", label: "è´¢å¡é¨é¨" }, |
| | | { value: "tech", label: "ææ¯é¨é¨" }, |
| | | ]; |
| | | |
| | | // æ¯å¦ä¸ºç¼è¾æ¨¡å¼ |
| | | const isEdit = ref(false); |
| | | |
| | | // ActionSheet æ¾ç¤ºç¶æ |
| | | const showPlanTypeActionSheet = ref(false); |
| | | const showUserActionSheet = ref(false); |
| | | const showTime = ref(false); |
| | | |
| | | // åå§åæ°æ® |
| | | const initData = () => { |
| | | const emergencyPlan = uni.getStorageSync("emergencyPlan") || {}; |
| | | if (emergencyPlan.id) { |
| | | // ç¼è¾æ¨¡å¼ |
| | | isEdit.value = true; |
| | | form.value = { |
| | | id: emergencyPlan.id, |
| | | planCode: emergencyPlan.planCode || "", |
| | | planName: emergencyPlan.planName || "", |
| | | publishTime: emergencyPlan.publishTime || "", |
| | | planType: emergencyPlan.planType || "", |
| | | coreResponsorUserId: emergencyPlan.coreResponsorUserId || "", |
| | | coreResponsorUserName: emergencyPlan.coreResponsorUserName || "", |
| | | remark: emergencyPlan.remark || "", |
| | | applyScope: emergencyPlan.applyScope |
| | | ? emergencyPlan.applyScope.split(",") |
| | | : [], |
| | | execSteps: emergencyPlan.execSteps || "", |
| | | }; |
| | | currentTime.value = new Date(emergencyPlan.publishTime).getTime(); |
| | | // è®¾ç½®é¢æ¡ç±»åæ ç¾ |
| | | const planTypeItem = emergencyPlanTypeOptions.value.find( |
| | | item => item.value === emergencyPlan.planType |
| | | ); |
| | | emergencyPlanTypeLabel.value = planTypeItem ? planTypeItem.name : ""; |
| | | console.log(form.value.applyScope, form.value.applyScope); |
| | | // åå§ååºæ¥å¤ç½®æ¥éª¤ |
| | | initExecSteps(emergencyPlan.execSteps); |
| | | } else { |
| | | // æ°å¢æ¨¡å¼ |
| | | isEdit.value = false; |
| | | form.value = { |
| | | planCode: "", |
| | | planName: "", |
| | | publishTime: new Date().toISOString().split("T")[0], |
| | | planType: "", |
| | | coreResponsorUserId: "", |
| | | coreResponsorUserName: "", |
| | | remark: "", |
| | | applyScope: [], |
| | | execSteps: "", |
| | | }; |
| | | emergencyPlanTypeLabel.value = ""; |
| | | execStepsList.value = []; |
| | | addExecStep(); |
| | | } |
| | | }; |
| | | const handleApplyScopeChange = e => { |
| | | // form.value.applyScope = e; |
| | | console.log(e, "e"); |
| | | console.log(form.value.applyScope, "form.value.applyScope"); |
| | | }; |
| | | |
| | | // åå§ååºæ¥å¤ç½®æ¥éª¤ |
| | | const initExecSteps = execSteps => { |
| | | if (execSteps) { |
| | | try { |
| | | execStepsList.value = JSON.parse(execSteps); |
| | | } catch (e) { |
| | | execStepsList.value = []; |
| | | } |
| | | } else { |
| | | execStepsList.value = []; |
| | | } |
| | | if (execStepsList.value.length === 0) { |
| | | addExecStep(); |
| | | } |
| | | }; |
| | | |
| | | // æ·»å åºæ¥å¤ç½®æ¥éª¤ |
| | | const addExecStep = () => { |
| | | const stepNumber = execStepsList.value.length + 1; |
| | | execStepsList.value.push({ |
| | | step: `æ¥éª¤${stepNumber}`, |
| | | description: "", |
| | | }); |
| | | }; |
| | | |
| | | // å é¤åºæ¥å¤ç½®æ¥éª¤ |
| | | const removeExecStep = index => { |
| | | if (execStepsList.value.length > 1) { |
| | | execStepsList.value.splice(index, 1); |
| | | } else { |
| | | showToast("è³å°ä¿çä¸ä¸ªæ¥éª¤"); |
| | | } |
| | | }; |
| | | |
| | | // è·åç¨æ·å表 |
| | | const getUserList = () => { |
| | | userListNoPage() |
| | | .then(res => { |
| | | userList.value = res.data.map(item => ({ |
| | | value: item.userId, |
| | | name: item.nickName, |
| | | })); |
| | | }) |
| | | .catch(() => { |
| | | showToast("è·åç¨æ·å表失败"); |
| | | }); |
| | | }; |
| | | |
| | | // æ¥æéæ©ç¡®è®¤ |
| | | const handleDateConfirm = e => { |
| | | form.value.publishTime = dayjs(e.value).format("YYYY-MM-DD"); |
| | | showTime.value = false; |
| | | }; |
| | | |
| | | // 颿¡ç±»åéæ©ç¡®è®¤ |
| | | const handlePlanTypeConfirm = e => { |
| | | form.value.planType = e.value; |
| | | const selectedType = emergencyPlanTypeOptions.value.find( |
| | | item => item.value === e.value |
| | | ); |
| | | if (selectedType) { |
| | | emergencyPlanTypeLabel.value = selectedType.name; |
| | | } |
| | | showPlanTypeActionSheet.value = false; |
| | | }; |
| | | |
| | | // ç¨æ·éæ©ç¡®è®¤ |
| | | const handleUserConfirm = e => { |
| | | form.value.coreResponsorUserId = e.value; |
| | | const selectedUser = userList.value.find(user => user.value === e.value); |
| | | if (selectedUser) { |
| | | form.value.coreResponsorUserName = selectedUser.name; |
| | | } |
| | | showUserActionSheet.value = false; |
| | | }; |
| | | |
| | | // è¿åä¸ä¸é¡µ |
| | | const goBack = () => { |
| | | uni.navigateBack(); |
| | | }; |
| | | |
| | | // 表åéªè¯è§å |
| | | const rules = { |
| | | planCode: [ |
| | | { |
| | | required: true, |
| | | message: "请è¾å
¥åºæ¥é¢æ¡ç¼ç ", |
| | | trigger: ["submit", "blur"], |
| | | }, |
| | | ], |
| | | planName: [ |
| | | { |
| | | required: true, |
| | | message: "请è¾å
¥åºæ¥é¢æ¡åç§°", |
| | | trigger: ["submit", "blur"], |
| | | }, |
| | | ], |
| | | publishTime: [ |
| | | { |
| | | required: true, |
| | | message: "è¯·éæ©åå¸çææ¶é´", |
| | | trigger: ["submit", "change"], |
| | | }, |
| | | ], |
| | | planType: [ |
| | | { |
| | | required: true, |
| | | message: "è¯·éæ©é¢æ¡ç±»å", |
| | | trigger: ["submit", "change"], |
| | | }, |
| | | ], |
| | | coreResponsorUserId: [ |
| | | { |
| | | required: true, |
| | | message: "è¯·éæ©æ ¸å¿è´£ä»»äºº", |
| | | trigger: ["submit", "change"], |
| | | }, |
| | | ], |
| | | applyScope: [ |
| | | { |
| | | required: true, |
| | | message: "è¯·éæ©éç¨èå´", |
| | | trigger: ["submit", "change"], |
| | | }, |
| | | ], |
| | | }; |
| | | |
| | | // æäº¤è¡¨å |
| | | const submitForm = async () => { |
| | | // éªè¯è¡¨åå¿
填项 |
| | | if (!formRef.value) return; |
| | | |
| | | const valid = await formRef.value.validate(); |
| | | if (!valid) { |
| | | return; |
| | | } |
| | | |
| | | // éªè¯åºæ¥å¤ç½®æ¥éª¤ |
| | | for (let i = 0; i < execStepsList.value.length; i++) { |
| | | const step = execStepsList.value[i]; |
| | | if (!step.step || !step.step.trim()) { |
| | | showToast(`第${i + 1}æ¡æ¥éª¤ç"æ¥éª¤"ä¸è½ä¸ºç©º`); |
| | | return; |
| | | } |
| | | if (!step.description || !step.description.trim()) { |
| | | showToast(`第${i + 1}æ¡æ¥éª¤ç"æªæ½"ä¸è½ä¸ºç©º`); |
| | | return; |
| | | } |
| | | } |
| | | |
| | | // å°åºæ¥å¤ç½®æ¥éª¤è½¬æ¢ä¸ºJSONå符串 |
| | | form.value.execSteps = JSON.stringify(execStepsList.value); |
| | | |
| | | // å¤çéç¨èå´ |
| | | form.value.applyScope = form.value.applyScope.join(","); |
| | | |
| | | showLoadingToast("ä¿åä¸..."); |
| | | |
| | | try { |
| | | if (isEdit.value) { |
| | | // ç¼è¾æ¨¡å¼ |
| | | const res = await safeContingencyPlanUpdate(form.value); |
| | | if (res.code === 200) { |
| | | showToast("æ´æ°æå"); |
| | | setTimeout(() => { |
| | | uni.navigateBack(); |
| | | }, 1000); |
| | | } else { |
| | | showToast(res.msg || "æ´æ°å¤±è´¥"); |
| | | } |
| | | } else { |
| | | // æ°å¢æ¨¡å¼ |
| | | const res = await safeContingencyPlanAdd(form.value); |
| | | if (res.code === 200) { |
| | | showToast("æ·»å æå"); |
| | | setTimeout(() => { |
| | | uni.navigateBack(); |
| | | }, 1000); |
| | | } else { |
| | | showToast(res.msg || "æ·»å 失败"); |
| | | } |
| | | } |
| | | } catch (error) { |
| | | console.error("æäº¤å¤±è´¥:", error); |
| | | showToast("æäº¤å¤±è´¥ï¼è¯·éè¯"); |
| | | } finally { |
| | | closeToast(); |
| | | } |
| | | }; |
| | | |
| | | // æ¾ç¤ºå è½½æç¤º |
| | | const showLoadingToast = message => { |
| | | uni.showLoading({ |
| | | title: message, |
| | | mask: true, |
| | | }); |
| | | }; |
| | | |
| | | // å
³éæç¤º |
| | | const closeToast = () => { |
| | | uni.hideLoading(); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | initData(); |
| | | getUserList(); |
| | | }); |
| | | |
| | | onShow(() => { |
| | | initData(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | @import "@/static/scss/form-common.scss"; |
| | | .emergency-plan-detail { |
| | | min-height: 100vh; |
| | | background: #f8f9fa; |
| | | padding-bottom: 100px; |
| | | } |
| | | |
| | | .form-section { |
| | | } |
| | | |
| | | .checkbox-group { |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | gap: 16px; |
| | | } |
| | | |
| | | .checkbox-item { |
| | | margin-right: 16px; |
| | | } |
| | | |
| | | .select-container { |
| | | position: relative; |
| | | width: 100%; |
| | | } |
| | | |
| | | .select-container .up-input { |
| | | width: 100%; |
| | | border: 1px solid #e4e7ed; |
| | | border-radius: 8px; |
| | | padding: 12px 16px; |
| | | background-color: #ffffff; |
| | | } |
| | | |
| | | .exec-steps-container { |
| | | padding: 20px; |
| | | background-color: #fff; |
| | | } |
| | | |
| | | .steps-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | margin-bottom: 20px; |
| | | padding-bottom: 12px; |
| | | border-bottom: 1px solid #e4e7ed; |
| | | } |
| | | |
| | | .steps-title { |
| | | font-size: 16px; |
| | | font-weight: 600; |
| | | color: #303133; |
| | | } |
| | | |
| | | .steps-count { |
| | | font-size: 14px; |
| | | color: #909399; |
| | | } |
| | | |
| | | .steps-list { |
| | | margin-bottom: 20px; |
| | | } |
| | | |
| | | .exec-step-item { |
| | | position: relative; |
| | | display: flex; |
| | | margin-bottom: 16px; |
| | | padding: 16px; |
| | | background-color: #ffffff; |
| | | border: 1px solid #e4e7ed; |
| | | border-radius: 8px; |
| | | transition: all 0.3s ease; |
| | | box-shadow: 0 1px 4px rgba(0, 0, 0, 0.05); |
| | | } |
| | | |
| | | .exec-step-item:hover { |
| | | box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1); |
| | | border-color: #409eff; |
| | | transform: translateY(-1px); |
| | | } |
| | | |
| | | .delete-btn { |
| | | position: absolute; |
| | | top: -25rpx; |
| | | right: -25rpx; |
| | | width: 50rpx; |
| | | height: 50rpx; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | text-align: center; |
| | | font-size: 20px; |
| | | border-radius: 50%; |
| | | background-color: red; |
| | | border: none; |
| | | z-index: 10; |
| | | } |
| | | |
| | | .delete-btn:hover { |
| | | transform: scale(1.1); |
| | | box-shadow: 0 3px 6px rgba(245, 108, 108, 0.4); |
| | | } |
| | | |
| | | .step-number { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | width: 32px; |
| | | height: 32px; |
| | | margin-right: 16px; |
| | | background-color: #ecf5ff; |
| | | color: #409eff; |
| | | font-size: 14px; |
| | | font-weight: 600; |
| | | border-radius: 50%; |
| | | flex-shrink: 0; |
| | | } |
| | | |
| | | .step-content { |
| | | flex: 1; |
| | | min-width: 0; |
| | | } |
| | | |
| | | .step-row { |
| | | display: flex; |
| | | align-items: flex-start; |
| | | margin-bottom: 12px; |
| | | } |
| | | |
| | | .step-row:last-child { |
| | | margin-bottom: 0; |
| | | } |
| | | |
| | | .step-label { |
| | | display: inline-block; |
| | | width: 80px; |
| | | font-size: 14px; |
| | | color: #606266; |
| | | margin-right: 12px; |
| | | flex-shrink: 0; |
| | | line-height: 36px; |
| | | } |
| | | |
| | | .step-input { |
| | | flex: 1; |
| | | min-width: 0; |
| | | } |
| | | |
| | | .step-input input { |
| | | font-size: 14px; |
| | | color: #303133; |
| | | } |
| | | |
| | | .step-textarea { |
| | | flex: 1; |
| | | min-width: 0; |
| | | } |
| | | |
| | | .step-textarea textarea { |
| | | font-size: 14px; |
| | | color: #303133; |
| | | min-height: 80px; |
| | | line-height: 1.5; |
| | | } |
| | | |
| | | .add-step-btn { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | width: 100%; |
| | | height: 44px; |
| | | line-height: 44px; |
| | | font-size: 14px; |
| | | border-radius: 8px; |
| | | transition: all 0.3s ease; |
| | | gap: 8px; |
| | | } |
| | | |
| | | .add-step-btn:hover { |
| | | transform: translateY(-1px); |
| | | box-shadow: 0 2px 8px rgba(64, 158, 255, 0.3); |
| | | } |
| | | |
| | | .add-step-btn text { |
| | | font-size: 14px; |
| | | } |
| | | |
| | | .bottom-buttons { |
| | | position: fixed; |
| | | bottom: 0; |
| | | left: 0; |
| | | right: 0; |
| | | display: flex; |
| | | padding: 16px 20px; |
| | | background: #ffffff; |
| | | border-top: 1px solid #f0f0f0; |
| | | gap: 16px; |
| | | } |
| | | |
| | | .bottom-btn { |
| | | flex: 1; |
| | | } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view class="emergency-plan-review"> |
| | | <!-- 使ç¨éç¨é¡µé¢å¤´é¨ç»ä»¶ --> |
| | | <PageHeader title="åºæ¥é¢æ¡å®¡æ ¸" |
| | | @back="goBack" /> |
| | | <!-- æç´¢åçéåºå --> |
| | | <view class="search-section"> |
| | | <view class="search-bar"> |
| | | <view class="search-input"> |
| | | <up-input class="search-text" |
| | | placeholder="请è¾å
¥åºæ¥é¢æ¡åç§°" |
| | | v-model="searchForm.planName" |
| | | @change="searchChange" |
| | | clearable /> |
| | | </view> |
| | | <view class="filter-button" |
| | | @click="getList"> |
| | | <u-icon name="search" |
| | | size="24" |
| | | color="#999"></u-icon> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <!-- åºæ¥é¢æ¡å表 --> |
| | | <view class="ledger-list" |
| | | v-if="planList.length > 0"> |
| | | <view v-for="(item, index) in planList" |
| | | :key="index"> |
| | | <view class="ledger-item"> |
| | | <view class="item-header"> |
| | | <view class="item-left"> |
| | | <view class="document-icon"> |
| | | <up-icon name="file-text" |
| | | size="16" |
| | | color="#ffffff"></up-icon> |
| | | </view> |
| | | <text class="item-title">{{ item.planName }}</text> |
| | | </view> |
| | | </view> |
| | | <up-divider></up-divider> |
| | | <view class="item-details" |
| | | @click="viewDetail(item)"> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">颿¡ç¼ç </text> |
| | | <text class="detail-value">{{ item.planCode || '-' }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">颿¡ç±»å</text> |
| | | <u-tag :type="getPlanTypeTagType(item.planType)"> |
| | | {{ emergencyPlanTypeLabel(item.planType) }} |
| | | </u-tag> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">åå¸çææ¶é´</text> |
| | | <text class="detail-value">{{ item.publishTime || '-' }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">æ ¸å¿è´£ä»»äºº</text> |
| | | <text class="detail-value">{{ item.coreResponsorUserName || '-' }}</text> |
| | | </view> |
| | | <view class="detail-row" |
| | | v-if="item.remark"> |
| | | <text class="detail-label">夿³¨</text> |
| | | <text class="detail-value">{{ item.remark }}</text> |
| | | </view> |
| | | </view> |
| | | <!-- æé®åºå --> |
| | | <view class="action-buttons"> |
| | | <u-button type="primary" |
| | | size="small" |
| | | class="action-btn" |
| | | @click="editPlan(item)"> |
| | | ç¼è¾ |
| | | </u-button> |
| | | <u-button type="info" |
| | | size="small" |
| | | class="action-btn" |
| | | @click="viewDetail(item)"> |
| | | æ¥ç详æ
|
| | | </u-button> |
| | | <u-button type="error" |
| | | size="small" |
| | | class="action-btn" |
| | | @click="deletePlan(item)"> |
| | | å é¤ |
| | | </u-button> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <view v-else |
| | | class="no-data"> |
| | | <text>ææ åºæ¥é¢æ¡</text> |
| | | </view> |
| | | <!-- æµ®å¨æ°å¢æé® --> |
| | | <view class="fab-button" |
| | | @click="addPlan"> |
| | | <up-icon name="plus" |
| | | size="24" |
| | | color="#ffffff"></up-icon> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, onMounted, computed } from "vue"; |
| | | import { onShow } from "@dcloudio/uni-app"; |
| | | import PageHeader from "@/components/PageHeader.vue"; |
| | | import { |
| | | safeContingencyPlanListPage, |
| | | safeContingencyPlanDel, |
| | | } from "@/api/safeProduction/emergencyPlanReview"; |
| | | import { useDict } from "@/utils/dict"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | |
| | | // æ¿æ¢ toast æ¹æ³ |
| | | defineOptions({ name: "emergency-plan-review-index" }); |
| | | const showToast = message => { |
| | | uni.showToast({ |
| | | title: message, |
| | | icon: "none", |
| | | }); |
| | | }; |
| | | |
| | | const userStore = useUserStore(); |
| | | |
| | | // æç´¢è¡¨å |
| | | const searchForm = ref({ |
| | | planName: "", |
| | | }); |
| | | |
| | | // åºæ¥é¢æ¡æ°æ® |
| | | const planList = ref([]); |
| | | |
| | | // åºæ¥é¢æ¡ç±»åé项 |
| | | const { emergency_plan_type } = useDict("emergency_plan_type"); |
| | | const emergencyPlanTypeOptions = computed( |
| | | () => emergency_plan_type?.value || [] |
| | | ); |
| | | |
| | | // è·å颿¡ç±»åæ ç¾ç±»å |
| | | const getPlanTypeTagType = planType => { |
| | | const typeMap = { |
| | | emergency: "warning", |
| | | fire: "danger", |
| | | natural: "info", |
| | | accident: "error", |
| | | }; |
| | | return typeMap[planType] || "info"; |
| | | }; |
| | | |
| | | // è·å颿¡ç±»åæ ç¾ææ¬ |
| | | const emergencyPlanTypeLabel = val => { |
| | | const item = emergencyPlanTypeOptions.value.find( |
| | | i => String(i.value) === String(val) |
| | | ); |
| | | return item ? item.label : val; |
| | | }; |
| | | |
| | | // è¿åä¸ä¸é¡µ |
| | | const goBack = () => { |
| | | uni.navigateBack(); |
| | | }; |
| | | const searchChange = val => { |
| | | searchForm.value.planName = val; |
| | | getList(); |
| | | }; |
| | | |
| | | // æ¥è¯¢å表 |
| | | const getList = () => { |
| | | showLoadingToast("å è½½ä¸..."); |
| | | const params = { |
| | | current: -1, |
| | | size: -1, |
| | | ...searchForm.value, |
| | | }; |
| | | safeContingencyPlanListPage(params) |
| | | .then(res => { |
| | | planList.value = res.records || res.data?.records || []; |
| | | closeToast(); |
| | | }) |
| | | .catch(() => { |
| | | closeToast(); |
| | | showToast("è·åæ°æ®å¤±è´¥"); |
| | | }); |
| | | }; |
| | | |
| | | // æ¾ç¤ºå è½½æç¤º |
| | | const showLoadingToast = message => { |
| | | uni.showLoading({ |
| | | title: message, |
| | | mask: true, |
| | | }); |
| | | }; |
| | | |
| | | // å
³éæç¤º |
| | | const closeToast = () => { |
| | | uni.hideLoading(); |
| | | }; |
| | | |
| | | // æ°å¢åºæ¥é¢æ¡ |
| | | const addPlan = () => { |
| | | uni.setStorageSync("emergencyPlan", {}); |
| | | uni.navigateTo({ |
| | | url: "/pages/safeProduction/emergencyPlanReview/detail", |
| | | }); |
| | | }; |
| | | |
| | | // ç¼è¾åºæ¥é¢æ¡ |
| | | const editPlan = item => { |
| | | uni.setStorageSync("emergencyPlan", item); |
| | | uni.navigateTo({ |
| | | url: "/pages/safeProduction/emergencyPlanReview/detail", |
| | | }); |
| | | }; |
| | | |
| | | // å é¤åºæ¥é¢æ¡ |
| | | const deletePlan = item => { |
| | | uni.showModal({ |
| | | title: "å é¤ç¡®è®¤", |
| | | content: `ç¡®å®è¦å é¤è¯¥åºæ¥é¢æ¡åï¼`, |
| | | success: res => { |
| | | if (res.confirm) { |
| | | deleteEmergencyPlan(item.id); |
| | | } |
| | | }, |
| | | }); |
| | | }; |
| | | |
| | | // å é¤åºæ¥é¢æ¡è®°å½ |
| | | const deleteEmergencyPlan = id => { |
| | | showLoadingToast("å é¤ä¸..."); |
| | | safeContingencyPlanDel([id]) |
| | | .then(() => { |
| | | closeToast(); |
| | | showToast("å 餿å"); |
| | | getList(); |
| | | }) |
| | | .catch(() => { |
| | | closeToast(); |
| | | showToast("å é¤å¤±è´¥"); |
| | | }); |
| | | }; |
| | | |
| | | // æ¥ç详æ
|
| | | const viewDetail = item => { |
| | | uni.setStorageSync("emergencyPlan", item); |
| | | uni.navigateTo({ |
| | | url: "/pages/safeProduction/emergencyPlanReview/view", |
| | | }); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getList(); |
| | | }); |
| | | |
| | | onShow(() => { |
| | | getList(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | @import "../../../styles/sales-common.scss"; |
| | | |
| | | // 页é¢ç¹å®çæ ·å¼è¦ç |
| | | .emergency-plan-review { |
| | | min-height: 100vh; |
| | | background: #f8f9fa; |
| | | position: relative; |
| | | } |
| | | |
| | | // ç¹å®ç徿 æ ·å¼ |
| | | .document-icon { |
| | | background: #2979ff; // ä¸é宿¨¡åä¿æä¸è´çèæ¯è² |
| | | } |
| | | |
| | | // ç¹ææ ·å¼ |
| | | .detail-value { |
| | | word-break: break-all; // ä¿ç页é¢ç¹æçææ¬æ¢è¡æ ·å¼ |
| | | } |
| | | |
| | | // ç¹å®çæµ®å¨æé®æ ·å¼ |
| | | .fab-button { |
| | | background: #2979ff; // ä¸é宿¨¡åä¿æä¸è´çèæ¯è² |
| | | box-shadow: 0 4px 16px rgba(41, 121, 255, 0.3); // ä¸é宿¨¡åä¿æä¸è´çé´å½±ææ |
| | | } |
| | | |
| | | // æä½æé®æ ·å¼ |
| | | .action-buttons { |
| | | display: flex; |
| | | gap: 12px; |
| | | padding: 0 0 16px 0; |
| | | justify-content: space-between; |
| | | } |
| | | |
| | | .action-btn { |
| | | flex: 1; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | gap: 8px; |
| | | } |
| | | |
| | | // åè¡¨å®¹å¨æ ·å¼ |
| | | .plan-list { |
| | | padding: 20px; |
| | | } |
| | | |
| | | // åè¡¨é¡¹æ ·å¼ |
| | | .plan-item { |
| | | background: #ffffff; |
| | | border-radius: 12px; |
| | | margin-bottom: 16px; |
| | | overflow: hidden; |
| | | box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05); |
| | | padding: 0 16px; |
| | | |
| | | &:active { |
| | | transform: scale(0.98); |
| | | box-shadow: 0 1px 4px rgba(0, 0, 0, 0.1); |
| | | } |
| | | } |
| | | |
| | | // 项ç®å¤´é¨æ ·å¼ |
| | | .item-header { |
| | | padding: 16px 0; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | } |
| | | |
| | | .item-left { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 8px; |
| | | } |
| | | |
| | | .item-title { |
| | | font-size: 14px; |
| | | color: #333; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | // 详æ
åºåæ ·å¼ |
| | | .item-details { |
| | | padding: 16px 0; |
| | | } |
| | | |
| | | .detail-row { |
| | | display: flex; |
| | | align-items: flex-end; |
| | | justify-content: space-between; |
| | | margin-bottom: 8px; |
| | | |
| | | &:last-child { |
| | | margin-bottom: 0; |
| | | } |
| | | } |
| | | |
| | | .detail-label { |
| | | font-size: 12px; |
| | | color: #777777; |
| | | min-width: 60px; |
| | | } |
| | | |
| | | .detail-value { |
| | | font-size: 12px; |
| | | color: #000000; |
| | | text-align: right; |
| | | flex: 1; |
| | | margin-left: 16px; |
| | | } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view class="emergency-plan-view"> |
| | | <!-- 使ç¨éç¨é¡µé¢å¤´é¨ç»ä»¶ --> |
| | | <PageHeader title="åºæ¥é¢æ¡è¯¦æ
" |
| | | @back="goBack" /> |
| | | <!-- 详æ
å
容 --> |
| | | <view class="detail-content" |
| | | v-if="currentPlan"> |
| | | <!-- åºæ¬ä¿¡æ¯ --> |
| | | <view class="info-section"> |
| | | <!-- <view class="section-title"> |
| | | <text class="title-text">{{ currentPlan.planName }}</text> |
| | | </view> --> |
| | | <view class="info-grid"> |
| | | <view class="info-item"> |
| | | <text class="info-label">åºæ¥é¢æ¡ç¼ç </text> |
| | | <text class="info-value">{{ currentPlan.planCode || '-' }}</text> |
| | | </view> |
| | | <view class="info-item"> |
| | | <text class="info-label">åºæ¥é¢æ¡åç§°</text> |
| | | <text class="info-value">{{ currentPlan.planName || '-' }}</text> |
| | | </view> |
| | | <view class="info-item"> |
| | | <text class="info-label">颿¡ç±»å</text> |
| | | <u-tag :type="getPlanTypeTagType(currentPlan.planType)"> |
| | | {{ emergencyPlanTypeLabel(currentPlan.planType) }} |
| | | </u-tag> |
| | | </view> |
| | | <view class="info-item"> |
| | | <text class="info-label">åå¸çææ¶é´</text> |
| | | <text class="info-value">{{ currentPlan.publishTime || '-' }}</text> |
| | | </view> |
| | | <view class="info-item"> |
| | | <text class="info-label">æ ¸å¿è´£ä»»äºº</text> |
| | | <text class="info-value">{{ currentPlan.coreResponsorUserName || '-' }}</text> |
| | | </view> |
| | | <view class="info-item"> |
| | | <text class="info-label">夿³¨</text> |
| | | <text class="info-value">{{ currentPlan.remark || '-' }}</text> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <!-- éç¨èå´ --> |
| | | <view class="scope-section"> |
| | | <view class="section-header"> |
| | | <text class="section-heading">éç¨èå´</text> |
| | | </view> |
| | | <view class="scope-tags"> |
| | | <u-tag v-for="(scope, index) in applyScopeList" |
| | | :key="index" |
| | | type="primary" |
| | | size="small" |
| | | class="scope-tag"> |
| | | {{ scope }} |
| | | </u-tag> |
| | | </view> |
| | | </view> |
| | | <!-- åºæ¥å¤ç½®æ¥éª¤ --> |
| | | <view class="steps-section"> |
| | | <view class="section-header"> |
| | | <text class="section-heading">åºæ¥å¤ç½®æ¥éª¤</text> |
| | | </view> |
| | | <view class="steps-list" |
| | | v-if="execStepsList.length > 0"> |
| | | <view v-for="(step, index) in execStepsList" |
| | | :key="index" |
| | | class="step-item"> |
| | | <view class="step-number">{{ index + 1 }}</view> |
| | | <view class="step-content"> |
| | | <text class="step-title">{{ step.step }}</text> |
| | | <text class="step-description">{{ step.description }}</text> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <view class="no-steps" |
| | | v-else> |
| | | <text>ææ åºæ¥å¤ç½®æ¥éª¤</text> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <!-- ç©ºç¶æ --> |
| | | <view class="empty-state" |
| | | v-else> |
| | | <text>ææ åºæ¥é¢æ¡ä¿¡æ¯</text> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, onMounted, computed } from "vue"; |
| | | import { onShow } from "@dcloudio/uni-app"; |
| | | import PageHeader from "@/components/PageHeader.vue"; |
| | | import { useDict } from "@/utils/dict"; |
| | | |
| | | // æ¿æ¢ toast æ¹æ³ |
| | | defineOptions({ name: "emergency-plan-view" }); |
| | | const showToast = message => { |
| | | uni.showToast({ |
| | | title: message, |
| | | icon: "none", |
| | | }); |
| | | }; |
| | | |
| | | // å½ååºæ¥é¢æ¡ |
| | | const currentPlan = ref(null); |
| | | |
| | | // åºæ¥å¤ç½®æ¥éª¤å表 |
| | | const execStepsList = ref([]); |
| | | |
| | | // éç¨èå´å表 |
| | | const applyScopeList = ref([]); |
| | | |
| | | // åºæ¥é¢æ¡ç±»åé项 |
| | | const { emergency_plan_type } = useDict("emergency_plan_type"); |
| | | const emergencyPlanTypeOptions = computed( |
| | | () => emergency_plan_type?.value || [] |
| | | ); |
| | | |
| | | // è·å颿¡ç±»åæ ç¾ç±»å |
| | | const getPlanTypeTagType = planType => { |
| | | const typeMap = { |
| | | emergency: "warning", |
| | | fire: "danger", |
| | | natural: "info", |
| | | accident: "error", |
| | | }; |
| | | return typeMap[planType] || "info"; |
| | | }; |
| | | |
| | | // è·å颿¡ç±»åæ ç¾ææ¬ |
| | | const emergencyPlanTypeLabel = val => { |
| | | const item = emergencyPlanTypeOptions.value.find( |
| | | i => String(i.value) === String(val) |
| | | ); |
| | | return item ? item.label : val; |
| | | }; |
| | | |
| | | // åå§åæ°æ® |
| | | const initData = () => { |
| | | const emergencyPlan = uni.getStorageSync("emergencyPlan") || {}; |
| | | if (emergencyPlan.id) { |
| | | currentPlan.value = emergencyPlan; |
| | | |
| | | // å¤çéç¨èå´ |
| | | if (emergencyPlan.applyScope) { |
| | | const scopes = emergencyPlan.applyScope.split(","); |
| | | applyScopeList.value = scopes.map(scope => { |
| | | const scopeMap = { |
| | | all: "å
¨ä½åå·¥", |
| | | manager: "管çå±", |
| | | hr: "人äºé¨é¨", |
| | | finance: "è´¢å¡é¨é¨", |
| | | tech: "ææ¯é¨é¨", |
| | | }; |
| | | return scopeMap[scope] || scope; |
| | | }); |
| | | } else { |
| | | applyScopeList.value = []; |
| | | } |
| | | |
| | | // å¤çåºæ¥å¤ç½®æ¥éª¤ |
| | | if (emergencyPlan.execSteps) { |
| | | try { |
| | | execStepsList.value = JSON.parse(emergencyPlan.execSteps); |
| | | } catch (e) { |
| | | execStepsList.value = []; |
| | | } |
| | | } else { |
| | | execStepsList.value = []; |
| | | } |
| | | } else { |
| | | currentPlan.value = null; |
| | | applyScopeList.value = []; |
| | | execStepsList.value = []; |
| | | showToast("æªæ¾å°åºæ¥é¢æ¡ä¿¡æ¯"); |
| | | } |
| | | }; |
| | | |
| | | // è¿åä¸ä¸é¡µ |
| | | const goBack = () => { |
| | | uni.navigateBack(); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | initData(); |
| | | }); |
| | | |
| | | onShow(() => { |
| | | initData(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | @import "../../../styles/sales-common.scss"; |
| | | |
| | | .emergency-plan-view { |
| | | min-height: 100vh; |
| | | background: #f8f9fa; |
| | | padding-bottom: 32px; |
| | | } |
| | | |
| | | .detail-content { |
| | | padding: 20px; |
| | | } |
| | | |
| | | // ä¿¡æ¯ section |
| | | .info-section { |
| | | background: #ffffff; |
| | | border-radius: 12px; |
| | | padding: 24px; |
| | | margin-bottom: 24px; |
| | | box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05); |
| | | } |
| | | |
| | | .section-title { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | margin-bottom: 24px; |
| | | } |
| | | |
| | | .title-text { |
| | | font-size: 18px; |
| | | font-weight: 600; |
| | | color: #303133; |
| | | flex: 1; |
| | | } |
| | | |
| | | .type-tag { |
| | | margin-left: 16px; |
| | | } |
| | | |
| | | .info-grid { |
| | | display: grid; |
| | | grid-template-columns: 1fr 1fr; |
| | | gap: 20px; |
| | | } |
| | | |
| | | .info-item { |
| | | display: flex; |
| | | flex-direction: column; |
| | | gap: 8px; |
| | | } |
| | | |
| | | .info-label { |
| | | font-size: 14px; |
| | | color: #909399; |
| | | } |
| | | |
| | | .info-value { |
| | | font-size: 14px; |
| | | color: #303133; |
| | | word-break: break-all; |
| | | } |
| | | |
| | | // éç¨èå´ section |
| | | .scope-section { |
| | | background: #ffffff; |
| | | border-radius: 12px; |
| | | padding: 24px; |
| | | margin-bottom: 24px; |
| | | box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05); |
| | | } |
| | | |
| | | .section-header { |
| | | margin-bottom: 16px; |
| | | } |
| | | |
| | | .section-heading { |
| | | font-size: 16px; |
| | | font-weight: 600; |
| | | color: #303133; |
| | | border-left: 4px solid #2979ff; |
| | | padding-left: 16px; |
| | | } |
| | | |
| | | .scope-tags { |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | gap: 12px; |
| | | } |
| | | |
| | | .scope-tag { |
| | | margin-bottom: 8px; |
| | | } |
| | | |
| | | // åºæ¥å¤ç½®æ¥éª¤ section |
| | | .steps-section { |
| | | background: #ffffff; |
| | | border-radius: 12px; |
| | | padding: 24px; |
| | | box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05); |
| | | } |
| | | |
| | | .steps-list { |
| | | margin-top: 16px; |
| | | } |
| | | |
| | | .step-item { |
| | | display: flex; |
| | | margin-bottom: 24px; |
| | | position: relative; |
| | | } |
| | | |
| | | .step-item::before { |
| | | content: ""; |
| | | position: absolute; |
| | | left: 15px; |
| | | top: 40px; |
| | | bottom: -24px; |
| | | width: 2px; |
| | | background-color: #eaeaea; |
| | | } |
| | | |
| | | .step-item:last-child::before { |
| | | display: none; |
| | | } |
| | | |
| | | .step-number { |
| | | width: 32px; |
| | | height: 32px; |
| | | border-radius: 50%; |
| | | background-color: #2979ff; |
| | | color: #ffffff; |
| | | font-size: 14px; |
| | | font-weight: 600; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | margin-right: 16px; |
| | | flex-shrink: 0; |
| | | margin-top: 4px; |
| | | } |
| | | |
| | | .step-content { |
| | | flex: 1; |
| | | } |
| | | |
| | | .step-title { |
| | | font-size: 16px; |
| | | font-weight: 600; |
| | | color: #303133; |
| | | display: block; |
| | | margin-bottom: 8px; |
| | | } |
| | | |
| | | .step-description { |
| | | font-size: 14px; |
| | | color: #606266; |
| | | line-height: 1.5; |
| | | word-break: break-all; |
| | | } |
| | | |
| | | .no-steps { |
| | | padding: 40px; |
| | | text-align: center; |
| | | color: #909399; |
| | | font-size: 14px; |
| | | background-color: #f8f9fa; |
| | | border-radius: 8px; |
| | | } |
| | | |
| | | // ç©ºç¶æ |
| | | .empty-state { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | height: 60vh; |
| | | font-size: 16px; |
| | | color: #909399; |
| | | } |
| | | </style> |
| | |
| | | <up-button type="primary" |
| | | size="small" |
| | | class="action-btn" |
| | | :disabled="item.invoicePerson !== userStore.nickName" |
| | | @click="openEdit(item)"> |
| | | ç¼è¾ |
| | | </up-button> |
| | |
| | | size="small" |
| | | plain |
| | | class="action-btn" |
| | | :disabled="item.invoicePerson !== userStore.nickName" |
| | | @click="handleDelete(item)"> |
| | | å é¤ |
| | | </up-button> |
| | |
| | | return |
| | | } |
| | | |
| | | const submitData = { |
| | | ...form.value, |
| | | productList: productData.value |
| | | } |
| | | // åç«¯è¦æ±ä»¥æ°ç»å½¢å¼æäº¤ï¼ä¿æåæ¥çå¯¹è±¡ç»æä¸åï¼åªå¨æå¤å±å
ä¸å±æ°ç» |
| | | const submitData = [ |
| | | { |
| | | ...form.value, |
| | | productList: productData.value |
| | | } |
| | | ] |
| | | |
| | | await invoiceRegistrationSave(submitData) |
| | | showToast('æäº¤æå') |
| | |
| | | <template> |
| | | <view class="account-detail"> |
| | | <!-- 使ç¨éç¨é¡µé¢å¤´é¨ç»ä»¶ --> |
| | | <PageHeader title="æ°å¢å款" @back="onClickLeft" /> |
| | | |
| | | <PageHeader title="æ°å¢å款" |
| | | @back="onClickLeft" /> |
| | | <!-- 表åå
容 --> |
| | | <u-form @submit="onSubmit" ref="formRef" label-width="110" input-align="right" error-message-align="right"> |
| | | <u-form @submit="onSubmit" |
| | | ref="formRef" |
| | | label-width="110" |
| | | input-align="right" |
| | | error-message-align="right"> |
| | | <!-- åºæ¬ä¿¡æ¯ --> |
| | | <u-cell-group title="åºæ¬ä¿¡æ¯"> |
| | | <u-form-item label="éå®ååå·" border-bottom> |
| | | <u-input |
| | | v-model="form.salesContractNo" |
| | | placeholder="èªå¨å¡«å
" |
| | | readonly |
| | | /> |
| | | <u-form-item label="éå®ååå·" |
| | | border-bottom> |
| | | <u-input v-model="form.salesContractNo" |
| | | placeholder="èªå¨å¡«å
" |
| | | readonly /> |
| | | </u-form-item> |
| | | <u-form-item label="客æ·åç§°" border-bottom> |
| | | <u-input |
| | | v-model="form.customerName" |
| | | placeholder="èªå¨å¡«å
" |
| | | readonly |
| | | /> |
| | | <u-form-item label="客æ·åç§°" |
| | | border-bottom> |
| | | <u-input v-model="form.customerName" |
| | | placeholder="èªå¨å¡«å
" |
| | | readonly /> |
| | | </u-form-item> |
| | | <u-form-item label="å票å·" border-bottom> |
| | | <!-- <u-form-item label="å票å·" border-bottom> |
| | | <u-input |
| | | v-model="form.invoiceNo" |
| | | placeholder="èªå¨å¡«å
" |
| | |
| | | placeholder="èªå¨å¡«å
" |
| | | readonly |
| | | /> |
| | | </u-form-item> --> |
| | | <u-form-item label="ç¨ç" |
| | | border-bottom> |
| | | <u-input v-model="form.taxRate" |
| | | placeholder="èªå¨å¡«å
" |
| | | readonly /> |
| | | </u-form-item> |
| | | <u-form-item label="ç¨ç" border-bottom> |
| | | <u-input |
| | | v-model="form.taxRate" |
| | | placeholder="èªå¨å¡«å
" |
| | | readonly |
| | | /> |
| | | <view class="tip-text">å¾
忬¾éé¢ï¼{{ form.pendingInvoiceTotal }} å
</view> |
| | | <u-form-item label="æ¬æ¬¡å款éé¢" |
| | | prop="receiptPaymentAmount" |
| | | required |
| | | border-bottom> |
| | | <u-input v-model="form.receiptPaymentAmount" |
| | | type="number" |
| | | placeholder="请è¾å
¥" |
| | | @blur="changeNum" |
| | | clearable /> |
| | | </u-form-item> |
| | | <view class="tip-text">å¾
忬¾éé¢ï¼{{ currentNoReceiptAmount }} å
</view> |
| | | <u-form-item label="æ¬æ¬¡å款éé¢" prop="receiptPaymentAmount" required border-bottom> |
| | | <u-input |
| | | v-model="form.receiptPaymentAmount" |
| | | type="number" |
| | | placeholder="请è¾å
¥" |
| | | @blur="changeNum" |
| | | clearable |
| | | /> |
| | | </u-form-item> |
| | | <u-form-item label="忬¾å½¢å¼" prop="receiptPaymentTypeName" required border-bottom> |
| | | <u-input |
| | | v-model="form.receiptPaymentTypeName" |
| | | placeholder="è¯·éæ©" |
| | | readonly |
| | | @click="showPaymentTypePicker" |
| | | /> |
| | | <u-form-item label="忬¾å½¢å¼" |
| | | prop="receiptPaymentTypeName" |
| | | required |
| | | border-bottom> |
| | | <u-input v-model="form.receiptPaymentTypeName" |
| | | placeholder="è¯·éæ©" |
| | | readonly |
| | | @click="showPaymentTypePicker" /> |
| | | <template #right> |
| | | <up-icon |
| | | name="arrow-right" |
| | | @click="showPaymentTypePicker" |
| | | ></up-icon> |
| | | </template> |
| | | <up-icon name="arrow-right" |
| | | @click="showPaymentTypePicker"></up-icon> |
| | | </template> |
| | | </u-form-item> |
| | | <u-form-item label="æ¥æ¬¾æ¥æ" prop="receiptPaymentDate" required border-bottom> |
| | | <u-input |
| | | v-model="form.receiptPaymentDate" |
| | | placeholder="è¯·éæ©" |
| | | readonly |
| | | @click="showDatePicker" |
| | | /> |
| | | <u-form-item label="æ¥æ¬¾æ¥æ" |
| | | prop="receiptPaymentDate" |
| | | required |
| | | border-bottom> |
| | | <u-input v-model="form.receiptPaymentDate" |
| | | placeholder="è¯·éæ©" |
| | | readonly |
| | | @click="showDatePicker" /> |
| | | <template #right> |
| | | <up-icon |
| | | name="arrow-right" |
| | | @click="showDatePicker" |
| | | ></up-icon> |
| | | </template> |
| | | <up-icon name="arrow-right" |
| | | @click="showDatePicker"></up-icon> |
| | | </template> |
| | | </u-form-item> |
| | | <u-form-item label="ç»è®°äºº" border-bottom> |
| | | <u-input |
| | | v-model="form.registrant" |
| | | placeholder="èªå¨å¡«å
" |
| | | readonly |
| | | /> |
| | | <u-form-item label="ç»è®°äºº" |
| | | border-bottom> |
| | | <u-input v-model="form.registrant" |
| | | placeholder="èªå¨å¡«å
" |
| | | readonly /> |
| | | </u-form-item> |
| | | </u-cell-group> |
| | | |
| | | <!-- æäº¤æé® --> |
| | | <FooterButtons |
| | | cancelText="åæ¶" |
| | | confirmText="ä¿å" |
| | | :loading="loading" |
| | | @cancel="onClickLeft" |
| | | @confirm="onSubmit" |
| | | /> |
| | | <FooterButtons cancelText="åæ¶" |
| | | confirmText="ä¿å" |
| | | :loading="loading" |
| | | @cancel="onClickLeft" |
| | | @confirm="onSubmit" /> |
| | | </u-form> |
| | | |
| | | <!-- 忬¾æ¹å¼éæ©å¨ --> |
| | | <up-action-sheet |
| | | :show="showPaymentType" |
| | | :actions="receiptPaymentType" |
| | | title="鿩忬¾å½¢å¼" |
| | | @select="onPaymentTypeConfirm" |
| | | @close="showPaymentType = false" |
| | | /> |
| | | |
| | | <up-action-sheet :show="showPaymentType" |
| | | :actions="receiptPaymentType" |
| | | title="鿩忬¾å½¢å¼" |
| | | @select="onPaymentTypeConfirm" |
| | | @close="showPaymentType = false" /> |
| | | <!-- æ¥æéæ©å¨ --> |
| | | <up-popup :show="showDate" mode="bottom" @close="showDate = false"> |
| | | <up-datetime-picker |
| | | :show="true" |
| | | v-model="currentDate" |
| | | @confirm="onDateConfirm" |
| | | @cancel="showDate = false" |
| | | mode="date" |
| | | /> |
| | | <up-popup :show="showDate" |
| | | mode="bottom" |
| | | @close="showDate = false"> |
| | | <up-datetime-picker :show="true" |
| | | v-model="currentDate" |
| | | @confirm="onDateConfirm" |
| | | @cancel="showDate = false" |
| | | mode="date" /> |
| | | </up-popup> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, onMounted, computed } from 'vue' |
| | | import FooterButtons from '@/components/FooterButtons.vue' |
| | | import { receiptPaymentSaveOrUpdate, invoiceInfo } from '@/api/salesManagement/receiptPayment' |
| | | import useUserStore from '@/store/modules/user' |
| | | import { useDict } from '@/utils/dict' |
| | | import { formatDateToYMD } from '@/utils/ruoyi' |
| | | import { ref, onMounted, computed } from "vue"; |
| | | import FooterButtons from "@/components/FooterButtons.vue"; |
| | | import { |
| | | receiptPaymentSaveOrUpdate, |
| | | invoiceInfo, |
| | | } from "@/api/salesManagement/receiptPayment"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | import { useDict } from "@/utils/dict"; |
| | | import { formatDateToYMD } from "@/utils/ruoyi"; |
| | | |
| | | // æ¾ç¤ºæç¤ºä¿¡æ¯ |
| | | const showToast = (message) => { |
| | | uni.showToast({ |
| | | title: message, |
| | | icon: 'none' |
| | | }) |
| | | } |
| | | // æ¾ç¤ºæç¤ºä¿¡æ¯ |
| | | const showToast = message => { |
| | | uni.showToast({ |
| | | title: message, |
| | | icon: "none", |
| | | }); |
| | | }; |
| | | |
| | | // æ¾ç¤ºå è½½æç¤º |
| | | const showLoadingToast = (message) => { |
| | | uni.showLoading({ |
| | | title: message, |
| | | mask: true |
| | | // æ¾ç¤ºå è½½æç¤º |
| | | const showLoadingToast = message => { |
| | | uni.showLoading({ |
| | | title: message, |
| | | mask: true, |
| | | }); |
| | | }; |
| | | |
| | | // å
³éå è½½æç¤º |
| | | const closeToast = () => { |
| | | uni.hideLoading(); |
| | | }; |
| | | |
| | | const userStore = useUserStore(); |
| | | |
| | | // 表åå¼ç¨ |
| | | const formRef = ref(); |
| | | |
| | | // ååºå¼æ°æ® |
| | | const loading = ref(false); |
| | | const showPaymentType = ref(false); |
| | | const pickerValue = ref([]); |
| | | const showDate = ref(false); |
| | | const currentDate = ref([ |
| | | new Date().getFullYear(), |
| | | new Date().getMonth() + 1, |
| | | new Date().getDate(), |
| | | ]); |
| | | |
| | | // è¡¨åæ°æ® |
| | | const form = ref({ |
| | | salesContractNo: "", |
| | | customerName: "", |
| | | invoiceNo: "", |
| | | invoiceTotal: "", |
| | | taxRate: "", |
| | | receiptPaymentAmount: "", |
| | | receiptPaymentType: "", |
| | | receiptPaymentTypeName: "", |
| | | registrant: "", |
| | | receiptPaymentDate: "", |
| | | invoiceLedgerId: "", |
| | | salesLedgerProductId: "", |
| | | }); |
| | | }; |
| | | const currentNoReceiptAmount = ref(0); |
| | | |
| | | // å
³éå è½½æç¤º |
| | | const closeToast = () => { |
| | | uni.hideLoading(); |
| | | }; |
| | | // è·ååå
¸æ°æ® |
| | | const { receipt_payment_type: dictReceiptPaymentType } = useDict( |
| | | "receipt_payment_type" |
| | | ); |
| | | |
| | | const userStore = useUserStore() |
| | | // 转æ¢åå
¸æ°æ®æ ¼å¼ä¸ºéæ©å¨éè¦çæ ¼å¼ |
| | | const receiptPaymentType = computed(() => { |
| | | return dictReceiptPaymentType.value.map(item => ({ |
| | | name: item.label, |
| | | value: item.value, |
| | | })); |
| | | }); |
| | | |
| | | // 表åå¼ç¨ |
| | | const formRef = ref() |
| | | // è¿åä¸ä¸é¡µ |
| | | const onClickLeft = () => { |
| | | uni.removeStorageSync("invoiceLedgerEditRow"); |
| | | uni.navigateBack(); |
| | | }; |
| | | |
| | | // ååºå¼æ°æ® |
| | | const loading = ref(false) |
| | | const showPaymentType = ref(false) |
| | | const pickerValue = ref([]) |
| | | const showDate = ref(false) |
| | | const currentDate = ref([new Date().getFullYear(), new Date().getMonth() + 1, new Date().getDate()]) |
| | | // æ¾ç¤ºå款æ¹å¼éæ©å¨ |
| | | const showPaymentTypePicker = () => { |
| | | showPaymentType.value = true; |
| | | }; |
| | | const changeNum = () => { |
| | | if (form.value.receiptPaymentAmount > form.value.pendingInvoiceTotal) { |
| | | form.value.receiptPaymentAmount = form.value.pendingInvoiceTotal; |
| | | showToast("ä¸å¯å¤§äºå¾
忬¾éé¢"); |
| | | } |
| | | }; |
| | | |
| | | // è¡¨åæ°æ® |
| | | const form = ref({ |
| | | salesContractNo: '', |
| | | customerName: '', |
| | | invoiceNo: '', |
| | | invoiceTotal: '', |
| | | taxRate: '', |
| | | receiptPaymentAmount: '', |
| | | receiptPaymentType: '', |
| | | receiptPaymentTypeName: '', |
| | | registrant: '', |
| | | receiptPaymentDate: '', |
| | | invoiceLedgerId: '' |
| | | }) |
| | | const currentNoReceiptAmount = ref(0) |
| | | // ç¡®è®¤åæ¬¾æ¹å¼éæ© |
| | | const onPaymentTypeConfirm = action => { |
| | | form.value.receiptPaymentType = action.value; |
| | | form.value.receiptPaymentTypeName = action.name; |
| | | showPaymentType.value = false; |
| | | }; |
| | | |
| | | // è·ååå
¸æ°æ® |
| | | const { receipt_payment_type: dictReceiptPaymentType } = useDict('receipt_payment_type') |
| | | // æ¾ç¤ºæ¥æéæ©å¨ |
| | | const showDatePicker = () => { |
| | | showDate.value = true; |
| | | }; |
| | | |
| | | // 转æ¢åå
¸æ°æ®æ ¼å¼ä¸ºéæ©å¨éè¦çæ ¼å¼ |
| | | const receiptPaymentType = computed(() => { |
| | | return dictReceiptPaymentType.value.map(item => ({ |
| | | name: item.label, |
| | | value: item.value |
| | | })) |
| | | }) |
| | | // ç¡®è®¤æ¥æéæ© |
| | | const onDateConfirm = e => { |
| | | form.value.receiptPaymentDate = formatDateToYMD(e.value); |
| | | currentDate.value = formatDateToYMD(e.value); |
| | | showDate.value = false; |
| | | }; |
| | | |
| | | // è¿åä¸ä¸é¡µ |
| | | const onClickLeft = () => { |
| | | uni.removeStorageSync('invoiceLedgerEditRow'); |
| | | uni.navigateBack() |
| | | } |
| | | // æäº¤è¡¨å |
| | | const onSubmit = () => { |
| | | // 表åéªè¯ |
| | | if (!form.value.receiptPaymentAmount) { |
| | | showToast("请è¾å
¥å款éé¢"); |
| | | return; |
| | | } |
| | | |
| | | // æ¾ç¤ºå款æ¹å¼éæ©å¨ |
| | | const showPaymentTypePicker = () => { |
| | | showPaymentType.value = true |
| | | } |
| | | const changeNum = () => { |
| | | if (form.value.receiptPaymentAmount > currentNoReceiptAmount.value) { |
| | | form.value.receiptPaymentAmount = currentNoReceiptAmount.value |
| | | showToast('ä¸å¯å¤§äºå¾
忬¾éé¢') |
| | | } |
| | | } |
| | | if (!form.value.receiptPaymentType) { |
| | | showToast("è¯·éæ©åæ¬¾å½¢å¼"); |
| | | return; |
| | | } |
| | | |
| | | // ç¡®è®¤åæ¬¾æ¹å¼éæ© |
| | | const onPaymentTypeConfirm = (action) => { |
| | | form.value.receiptPaymentType = action.value |
| | | form.value.receiptPaymentTypeName = action.name |
| | | showPaymentType.value = false |
| | | } |
| | | if (!form.value.receiptPaymentDate) { |
| | | showToast("è¯·éæ©æ¥æ¬¾æ¥æ"); |
| | | return; |
| | | } |
| | | |
| | | // æ¾ç¤ºæ¥æéæ©å¨ |
| | | const showDatePicker = () => { |
| | | showDate.value = true |
| | | } |
| | | loading.value = true; |
| | | form.value.receiptPaymentAmount = Number(form.value.receiptPaymentAmount); |
| | | receiptPaymentSaveOrUpdate([form.value]) |
| | | .then(() => { |
| | | showToast("æäº¤æå"); |
| | | // éç¥ä¸ä¸é¡µå·æ°æ°æ® |
| | | const pages = getCurrentPages(); |
| | | const prevPage = pages[pages.length - 2]; |
| | | if (prevPage && prevPage.$vm && prevPage.$vm.getList) { |
| | | prevPage.$vm.getList(); |
| | | } |
| | | uni.removeStorageSync("invoiceLedgerEditRow"); |
| | | uni.navigateBack(); |
| | | }) |
| | | .catch(error => { |
| | | loading.value = false; |
| | | }); |
| | | }; |
| | | |
| | | // ç¡®è®¤æ¥æéæ© |
| | | const onDateConfirm = (e) => { |
| | | form.value.receiptPaymentDate = formatDateToYMD(e.value) |
| | | currentDate.value = formatDateToYMD(e.value) |
| | | showDate.value = false; |
| | | } |
| | | // åå§åæ°æ® |
| | | const initData = () => { |
| | | const rowStr = uni.getStorageSync("invoiceLedgerEditRow"); |
| | | const row = JSON.parse(rowStr); |
| | | form.value = { ...row }; |
| | | form.value.invoiceLedgerId = form.value.id; |
| | | form.value.salesLedgerProductId = form.value.id; |
| | | form.value.id = ""; |
| | | currentNoReceiptAmount.value = row.noReceiptAmount; |
| | | form.value.registrant = userStore.nickName; |
| | | |
| | | // æäº¤è¡¨å |
| | | const onSubmit = () => { |
| | | // 表åéªè¯ |
| | | if (!form.value.receiptPaymentAmount) { |
| | | showToast('请è¾å
¥å款éé¢') |
| | | return |
| | | } |
| | | |
| | | if (!form.value.receiptPaymentType) { |
| | | showToast('è¯·éæ©åæ¬¾å½¢å¼') |
| | | return |
| | | } |
| | | |
| | | if (!form.value.receiptPaymentDate) { |
| | | showToast('è¯·éæ©æ¥æ¬¾æ¥æ') |
| | | return |
| | | } |
| | | // invoiceInfo({ id: row.id }) |
| | | // .then(res => { |
| | | // const data = res.data; |
| | | // form.value = { ...data }; |
| | | // form.value.invoiceLedgerId = form.value.id; |
| | | // form.value.id = ""; |
| | | // currentNoReceiptAmount.value = row.noReceiptAmount; |
| | | // form.value.registrant = userStore.nickName; |
| | | // }) |
| | | // .catch(() => { |
| | | // showToast("è·åæ°æ®å¤±è´¥"); |
| | | // }); |
| | | }; |
| | | |
| | | loading.value = true |
| | | |
| | | receiptPaymentSaveOrUpdate(form.value) |
| | | .then(() => { |
| | | showToast('æäº¤æå') |
| | | // éç¥ä¸ä¸é¡µå·æ°æ°æ® |
| | | const pages = getCurrentPages(); |
| | | const prevPage = pages[pages.length - 2]; |
| | | if (prevPage && prevPage.$vm && prevPage.$vm.getList) { |
| | | prevPage.$vm.getList(); |
| | | } |
| | | uni.removeStorageSync('invoiceLedgerEditRow'); |
| | | uni.navigateBack() |
| | | }) |
| | | .catch((error) => { |
| | | loading.value = false |
| | | }) |
| | | } |
| | | |
| | | // åå§åæ°æ® |
| | | const initData = () => { |
| | | const rowStr = uni.getStorageSync('invoiceLedgerEditRow') |
| | | const row = JSON.parse(rowStr) |
| | | invoiceInfo({ id: row.id }).then((res) => { |
| | | const data = res.data |
| | | form.value = { ...data} |
| | | form.value.invoiceLedgerId = form.value.id; |
| | | form.value.id = ""; |
| | | currentNoReceiptAmount.value = row.noReceiptAmount |
| | | form.value.registrant = userStore.nickName |
| | | }).catch(() => { |
| | | showToast('è·åæ°æ®å¤±è´¥') |
| | | }) |
| | | } |
| | | |
| | | onMounted(() => { |
| | | initData() |
| | | }) |
| | | onMounted(() => { |
| | | initData(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | @import '@/static/scss/form-common.scss'; |
| | | @import "@/static/scss/form-common.scss"; |
| | | .tip-text { |
| | | font-size: 14px; |
| | | color: #999; |
| | | margin-top: 20rpx; |
| | | margin-bottom: 20rpx; |
| | | } |
| | | </style> |
| | |
| | | <text class="detail-value">{{ item.customerName }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">客æ·ååå·</text> |
| | | <text class="detail-value">{{ item.customerContractNo }}</text> |
| | | <text class="detail-label">éå®ååå·</text> |
| | | <text class="detail-value">{{ item.salesContractNo }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">项ç®åç§°</text> |
| | |
| | | <text class="detail-value">{{ item.productCategory }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">å票å·</text> |
| | | <text class="detail-value">{{ item.invoiceNo || '-' }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">å票éé¢(å
)</text> |
| | | <text class="detail-value highlight">{{ formatNumber(item.invoiceTotal) }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">ç¨ç(%)</text> |
| | | <text class="detail-value">{{ item.taxRate }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">忬¾éé¢(å
)</text> |
| | | <text class="detail-value highlight">{{ formatNumber(item.receiptPaymentAmountTotal) }}</text> |
| | | <text class="detail-value highlight">{{ formatNumber(item.invoiceTotal) }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">å¾
忬¾éé¢(å
)</text> |
| | | <text class="detail-value danger">{{ formatNumber(item.noReceiptAmount) }}</text> |
| | | <text class="detail-value danger">{{ formatNumber(item.pendingInvoiceTotal) }}</text> |
| | | </view> |
| | | </view> |
| | | <!-- æä½æé® --> |
| | |
| | | if (!type) { |
| | | return "info"; |
| | | } |
| | | if (type == "æªå®æå款") { |
| | | if (type == "æªå®æä»æ¬¾") { |
| | | return "warning"; |
| | | } else { |
| | | return "success"; |
| | |
| | | <template> |
| | | <view class="sales-account"> |
| | | <!-- 使ç¨éç¨é¡µé¢å¤´é¨ç»ä»¶ --> |
| | | <PageHeader title="客æ·å¾æ¥" @back="goBack" /> |
| | | |
| | | <!-- æç´¢åºå --> |
| | | <view class="search-section"> |
| | | <view class="search-bar"> |
| | | <view class="search-input"> |
| | | <up-input |
| | | class="search-text" |
| | | placeholder="请è¾å
¥å®¢æ·åç§°" |
| | | v-model="searchForm.customerName" |
| | | @change="handleQuery" |
| | | clearable |
| | | /> |
| | | </view> |
| | | <view class="search-button" @click="handleQuery"> |
| | | <up-icon name="search" size="24" color="#999"></up-icon> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- 客æ·å表 --> |
| | | <view class="customer-list-container"> |
| | | <view class="customer-list" v-if="tableData.length > 0"> |
| | | <view |
| | | v-for="(item, index) in tableData" |
| | | :key="item.id" |
| | | class="customer-item" |
| | | @click="rowClickMethod(item)" |
| | | > |
| | | <view class="item-header"> |
| | | <view class="item-left"> |
| | | <view class="customer-icon"> |
| | | <up-icon name="file-text" size="16" color="#ffffff"></up-icon> |
| | | </view> |
| | | <text class="customer-name">{{ item.customerName }}</text> |
| | | </view> |
| | | <view class="item-right"> |
| | | <up-icon name="arrow-right" size="16" color="#999"></up-icon> |
| | | </view> |
| | | </view> |
| | | <up-divider></up-divider> |
| | | <view class="item-details"> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">å¼ç¥¨éé¢(å
)</text> |
| | | <text class="detail-value">{{ formattedNumber(item.invoiceTotal) }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">忬¾éé¢(å
)</text> |
| | | <text class="detail-value">{{ formattedNumber(item.receiptPaymentAmount) }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">åºæ¶éé¢(å
)</text> |
| | | <text class="detail-value highlight danger">{{ formattedNumber(item.unReceiptPaymentAmount) }}</text> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <view v-else class="no-data"> |
| | | <text>ææ å®¢æ·æ°æ®</text> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <view class="sales-account"> |
| | | <!-- 使ç¨éç¨é¡µé¢å¤´é¨ç»ä»¶ --> |
| | | <PageHeader title="客æ·å¾æ¥" |
| | | @back="goBack" /> |
| | | <!-- æç´¢åºå --> |
| | | <view class="search-section"> |
| | | <view class="search-bar"> |
| | | <view class="search-input"> |
| | | <up-input class="search-text" |
| | | placeholder="请è¾å
¥å®¢æ·åç§°" |
| | | v-model="searchForm.searchText" |
| | | @change="searchChange" |
| | | clearable /> |
| | | </view> |
| | | <view class="search-button" |
| | | @click="handleQuery"> |
| | | <up-icon name="search" |
| | | size="24" |
| | | color="#999"></up-icon> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <!-- 客æ·å表 --> |
| | | <view class="customer-list-container"> |
| | | <view class="customer-list" |
| | | v-if="tableData.length > 0"> |
| | | <view v-for="(item, index) in tableData" |
| | | :key="item.id" |
| | | class="customer-item" |
| | | @click="rowClickMethod(item)"> |
| | | <view class="item-header"> |
| | | <view class="item-left"> |
| | | <view class="customer-icon"> |
| | | <up-icon name="file-text" |
| | | size="16" |
| | | color="#ffffff"></up-icon> |
| | | </view> |
| | | <text class="customer-name">{{ item.customerName }}</text> |
| | | </view> |
| | | <view class="item-right"> |
| | | <up-icon name="arrow-right" |
| | | size="16" |
| | | color="#999"></up-icon> |
| | | </view> |
| | | </view> |
| | | <up-divider></up-divider> |
| | | <view class="item-details"> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">å¼ç¥¨éé¢(å
)</text> |
| | | <text class="detail-value">{{ formattedNumber(item.invoiceTotal) }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">忬¾éé¢(å
)</text> |
| | | <text class="detail-value">{{ formattedNumber(item.receiptPaymentAmount) }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">åºæ¶éé¢(å
)</text> |
| | | <text class="detail-value highlight danger">{{ formattedNumber(item.unReceiptPaymentAmount) }}</text> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <view v-else |
| | | class="no-data"> |
| | | <text>ææ å®¢æ·æ°æ®</text> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { onMounted, ref, reactive, toRefs } from "vue"; |
| | | import { onShow } from '@dcloudio/uni-app'; |
| | | import { invoiceLedgerSalesAccount } from "@/api/salesManagement/invoiceLedger"; |
| | | import { onMounted, ref, reactive, toRefs } from "vue"; |
| | | import { onShow } from "@dcloudio/uni-app"; |
| | | import { invoiceLedgerSalesAccount } from "@/api/salesManagement/invoiceLedger"; |
| | | |
| | | const tableData = ref([]); |
| | | |
| | | const tableData = ref([]); |
| | | const page = reactive({ |
| | | current: -1, |
| | | size: -1, |
| | | }); |
| | | |
| | | const page = reactive({ |
| | | current: -1, |
| | | size: -1, |
| | | }); |
| | | const data = reactive({ |
| | | searchForm: { |
| | | searchText: "", |
| | | invoiceDate: "", |
| | | }, |
| | | }); |
| | | |
| | | const { searchForm } = toRefs(data); |
| | | |
| | | // è¿åä¸ä¸é¡µ |
| | | const goBack = () => { |
| | | uni.navigateBack(); |
| | | }; |
| | | // æç´¢æ¡ååæ¶è§¦å |
| | | const searchChange = val => { |
| | | searchForm.value.searchText = val; |
| | | getList(); |
| | | }; |
| | | // æ¥è¯¢å表 |
| | | const handleQuery = () => { |
| | | getList(); |
| | | }; |
| | | |
| | | const data = reactive({ |
| | | searchForm: { |
| | | customerName: "", |
| | | invoiceDate: "", |
| | | }, |
| | | }); |
| | | const getList = () => { |
| | | showLoadingToast("å è½½ä¸..."); |
| | | invoiceLedgerSalesAccount({ ...searchForm.value, ...page }) |
| | | .then(res => { |
| | | tableData.value = res.data.records; |
| | | closeToast(); |
| | | }) |
| | | .catch(() => { |
| | | closeToast(); |
| | | uni.showToast({ |
| | | title: "æ¥è¯¢å¤±è´¥", |
| | | icon: "error", |
| | | }); |
| | | }); |
| | | }; |
| | | |
| | | const { searchForm } = toRefs(data); |
| | | const formattedNumber = value => { |
| | | return parseFloat(value || 0).toFixed(2); |
| | | }; |
| | | |
| | | // è¿åä¸ä¸é¡µ |
| | | const goBack = () => { |
| | | uni.navigateBack(); |
| | | }; |
| | | // æ¾ç¤ºå è½½æç¤º |
| | | const showLoadingToast = message => { |
| | | uni.showLoading({ |
| | | title: message, |
| | | mask: true, |
| | | }); |
| | | }; |
| | | |
| | | // æ¥è¯¢å表 |
| | | const handleQuery = () => { |
| | | getList(); |
| | | }; |
| | | // å
³éæç¤º |
| | | const closeToast = () => { |
| | | uni.hideLoading(); |
| | | }; |
| | | |
| | | const getList = () => { |
| | | showLoadingToast('å è½½ä¸...') |
| | | invoiceLedgerSalesAccount({ ...searchForm.value, ...page }).then((res) => { |
| | | tableData.value = res.data.records; |
| | | closeToast() |
| | | }).catch(() => { |
| | | closeToast() |
| | | uni.showToast({ |
| | | title: 'æ¥è¯¢å¤±è´¥', |
| | | icon: 'error' |
| | | }); |
| | | }); |
| | | }; |
| | | const rowClickMethod = row => { |
| | | // ä½¿ç¨ uni.setStorageSync åå¨å®¢æ·ä¿¡æ¯ |
| | | uni.setStorageSync("customerId", row.id); |
| | | // 跳转å°åæ¬¾è®°å½æç»é¡µé¢ |
| | | uni.navigateTo({ |
| | | url: "/pages/sales/receiptPaymentLedger/detail", |
| | | }); |
| | | }; |
| | | |
| | | const formattedNumber = (value) => { |
| | | return parseFloat(value || 0).toFixed(2); |
| | | }; |
| | | onShow(() => { |
| | | // 页颿¾ç¤ºæ¶å·æ°å表 |
| | | getList(); |
| | | }); |
| | | |
| | | // æ¾ç¤ºå è½½æç¤º |
| | | const showLoadingToast = (message) => { |
| | | uni.showLoading({ |
| | | title: message, |
| | | mask: true |
| | | }); |
| | | }; |
| | | |
| | | // å
³éæç¤º |
| | | const closeToast = () => { |
| | | uni.hideLoading(); |
| | | }; |
| | | |
| | | const rowClickMethod = (row) => { |
| | | // ä½¿ç¨ uni.setStorageSync åå¨å®¢æ·ä¿¡æ¯ |
| | | uni.setStorageSync('customerId', row.id); |
| | | // 跳转å°åæ¬¾è®°å½æç»é¡µé¢ |
| | | uni.navigateTo({ |
| | | url: '/pages/sales/receiptPaymentLedger/detail' |
| | | }); |
| | | }; |
| | | |
| | | onShow(() => { |
| | | // 页颿¾ç¤ºæ¶å·æ°å表 |
| | | getList(); |
| | | }); |
| | | |
| | | onMounted(() => { |
| | | getList(); |
| | | }); |
| | | onMounted(() => { |
| | | getList(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | @import '@/styles/sales-common.scss'; |
| | | @import "@/styles/sales-common.scss"; |
| | | |
| | | // 客æ·å¾æ¥ç¹ææ ·å¼ |
| | | .detail-value.danger { |
| | | color: #ff4757; // ä¸å
Œ
±æ ·å¼ä¸ç #ee0a24 ä¸å |
| | | font-weight: 500; |
| | | } |
| | | // 客æ·å¾æ¥ç¹ææ ·å¼ |
| | | .detail-value.danger { |
| | | color: #ff4757; // ä¸å
Œ
±æ ·å¼ä¸ç #ee0a24 ä¸å |
| | | font-weight: 500; |
| | | } |
| | | </style> |
| | |
| | | @click="showPicker = true"></up-icon> |
| | | </template> |
| | | </up-form-item> |
| | | <up-form-item label="客æ·ååå·" |
| | | prop="customerContractNo" |
| | | required> |
| | | <up-input v-model="form.customerContractNo" |
| | | placeholder="请è¾å
¥å®¢æ·ååå·" /> |
| | | </up-form-item> |
| | | <up-form-item label="客æ·åç§°" |
| | | prop="customerName" |
| | | required> |
| | |
| | | const form = ref({ |
| | | id: "", |
| | | salesContractNo: "", |
| | | customerContractNo: "", |
| | | customerId: "", |
| | | customerName: "", |
| | | projectName: "", |
| | |
| | | // è¡¨åæ ¡éªè§å |
| | | const rules = { |
| | | salesman: [{ required: true, message: "è¯·éæ©ä¸å¡å", trigger: "change" }], |
| | | customerContractNo: [ |
| | | { required: true, message: "请è¾å
¥å®¢æ·ååå·", trigger: "blur" }, |
| | | ], |
| | | customerName: [ |
| | | { required: true, message: "è¯·éæ©å®¢æ·åç§°", trigger: "change" }, |
| | | ], |
| | |
| | | console.log(editData.value); |
| | | // å¡«å
åºæ¬ä¿¡æ¯ |
| | | form.value.salesContractNo = editData.value.salesContractNo || ""; |
| | | form.value.customerContractNo = editData.value.customerContractNo || ""; |
| | | form.value.customerName = editData.value.customerName || ""; |
| | | form.value.projectName = editData.value.projectName || ""; |
| | | form.value.executionDate = editData.value.executionDate || ""; |
| | |
| | | <text class="detail-value">{{ item.customerName }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">客æ·ååå·</text> |
| | | <text class="detail-value">{{ item.customerContractNo }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">ä¸å¡å</text> |
| | | <text class="detail-value">{{ item.salesman }}</text> |
| | | </view> |
| | |
| | | <text class="info-value">{{ form.salesContractNo }}</text> |
| | | </view> |
| | | <view class="info-item"> |
| | | <text class="info-label">客æ·ååå·</text> |
| | | <text class="info-value highlight">{{ form.customerContractNo }}</text> |
| | | </view> |
| | | <view class="info-item"> |
| | | <text class="info-label">客æ·åç§°</text> |
| | | <text class="info-value">{{ form.customerName }}</text> |
| | | </view> |
| | |
| | | const form = ref({ |
| | | id: "", |
| | | salesContractNo: "", |
| | | customerContractNo: "", |
| | | customerId: "", |
| | | customerName: "", |
| | | projectName: "", |