Commit 3d077e99e337a6d863bf7031d038c84bad543822

Authored by wuxw
1 parent 66eb78ed

开发完成采购物品功能

src/api/resource/resourceStoreManageApi.js 0 → 100644
  1 +import request from '@/utils/request'
  2 +import { getCommunityId } from "@/api/community/communityApi"
  3 +
  4 +// 获取物品列表
  5 +export function listResourceStores(params) {
  6 + return new Promise((resolve, reject) => {
  7 + request({
  8 + url: '/resourceStore.listResourceStores',
  9 + method: 'get',
  10 + params
  11 + }).then(response => {
  12 + const res = response.data
  13 + resolve(res)
  14 + }).catch(error => {
  15 + reject(error)
  16 + })
  17 + })
  18 +}
  19 +
  20 +// 获取仓库列表
  21 +export function listStorehouses(params) {
  22 + return new Promise((resolve, reject) => {
  23 + request({
  24 + url: '/resourceStore.listStorehouses',
  25 + method: 'get',
  26 + params
  27 + }).then(response => {
  28 + const res = response.data
  29 + if (res.code === 0) {
  30 + resolve({ data: res.data })
  31 + } else {
  32 + reject(new Error(res.msg || '获取仓库列表失败'))
  33 + }
  34 + }).catch(error => {
  35 + reject(error)
  36 + })
  37 + })
  38 +}
  39 +
  40 +// 获取物品规格列表
  41 +export function listResourceStoreSpecifications(params) {
  42 + return new Promise((resolve, reject) => {
  43 + request({
  44 + url: '/resourceStore.listResourceStoreSpecifications',
  45 + method: 'get',
  46 + params
  47 + }).then(response => {
  48 + const res = response.data
  49 + if (res.code === 0) {
  50 + resolve({ data: res.data })
  51 + } else {
  52 + reject(new Error(res.msg || '获取物品规格列表失败'))
  53 + }
  54 + }).catch(error => {
  55 + reject(error)
  56 + })
  57 + })
  58 +}
  59 +
  60 +// 获取物品类型列表
  61 +export function listResourceStoreTypes(params) {
  62 + return new Promise((resolve, reject) => {
  63 + request({
  64 + url: '/resourceStoreType.listResourceStoreTypes',
  65 + method: 'get',
  66 + params
  67 + }).then(response => {
  68 + const res = response.data
  69 + if (res.code === 0) {
  70 + resolve({ data: res.data })
  71 + } else {
  72 + reject(new Error(res.msg || '获取物品类型列表失败'))
  73 + }
  74 + }).catch(error => {
  75 + reject(error)
  76 + })
  77 + })
  78 +}
  79 +
  80 +// 删除物品
  81 +export function deleteResourceStore(data) {
  82 + return new Promise((resolve, reject) => {
  83 + request({
  84 + url: '/resourceStore.deleteResourceStore',
  85 + method: 'post',
  86 + data
  87 + }).then(response => {
  88 + const res = response.data
  89 + if (res.code === 0) {
  90 + resolve(res)
  91 + } else {
  92 + reject(new Error(res.msg || '删除物品失败'))
  93 + }
  94 + }).catch(error => {
  95 + reject(error)
  96 + })
  97 + })
  98 +}
  99 +
  100 +// 保存物品
  101 +export function saveResourceStore(data) {
  102 + return new Promise((resolve, reject) => {
  103 + request({
  104 + url: '/resourceStore.saveResourceStore',
  105 + method: 'post',
  106 + data
  107 + }).then(response => {
  108 + const res = response.data
  109 + if (res.code === 0) {
  110 + resolve(res)
  111 + } else {
  112 + reject(new Error(res.msg || '保存物品失败'))
  113 + }
  114 + }).catch(error => {
  115 + reject(error)
  116 + })
  117 + })
  118 +}
  119 +
  120 +// 更新物品
  121 +export function updateResourceStore(data) {
  122 + return new Promise((resolve, reject) => {
  123 + request({
  124 + url: '/resourceStore.updateResourceStore',
  125 + method: 'post',
  126 + data
  127 + }).then(response => {
  128 + const res = response.data
  129 + if (res.code === 0) {
  130 + resolve(res)
  131 + } else {
  132 + reject(new Error(res.msg || '更新物品失败'))
  133 + }
  134 + }).catch(error => {
  135 + reject(error)
  136 + })
  137 + })
  138 +}
  139 +
  140 +// 导出数据
  141 +export function exportData(params) {
  142 + return new Promise((resolve, reject) => {
  143 + request({
  144 + url: '/export.exportData',
  145 + method: 'get',
  146 + params
  147 + }).then(response => {
  148 + const res = response.data
  149 + if (res.code === 0) {
  150 + resolve(res)
  151 + } else {
  152 + reject(new Error(res.msg || '导出数据失败'))
  153 + }
  154 + }).catch(error => {
  155 + reject(error)
  156 + })
  157 + })
  158 +}
  159 +
  160 +// 导入数据
  161 +export function importData(data) {
  162 + return new Promise((resolve, reject) => {
  163 + request({
  164 + url: '/importResourceStore.importData',
  165 + method: 'post',
  166 + data,
  167 + headers: {
  168 + 'Content-Type': 'multipart/form-data'
  169 + }
  170 + }).then(response => {
  171 + const res = response.data
  172 + if (res.code === 0) {
  173 + resolve(res)
  174 + } else {
  175 + reject(new Error(res.msg || '导入数据失败'))
  176 + }
  177 + }).catch(error => {
  178 + reject(error)
  179 + })
  180 + })
  181 +}
  182 +
  183 +// 获取物品总价
  184 +export function listResourceStoreTimes(params) {
  185 + return new Promise((resolve, reject) => {
  186 + request({
  187 + url: '/resourceStoreTimes.listResourceStoreTimes',
  188 + method: 'get',
  189 + params
  190 + }).then(response => {
  191 + const res = response.data
  192 + if (res.code === 0) {
  193 + resolve({ data: res.data, totalPrice: res.totalPrice })
  194 + } else {
  195 + reject(new Error(res.msg || '获取物品总价失败'))
  196 + }
  197 + }).catch(error => {
  198 + reject(error)
  199 + })
  200 + })
  201 +}
  202 +
  203 +// 保存物品类型
  204 +export function saveResourceStoreType(data) {
  205 + return new Promise((resolve, reject) => {
  206 + request({
  207 + url: '/resourceStoreType.saveResourceStoreType',
  208 + method: 'post',
  209 + data
  210 + }).then(response => {
  211 + const res = response.data
  212 + if (res.code === 0) {
  213 + resolve(res)
  214 + } else {
  215 + reject(new Error(res.msg || '保存物品类型失败'))
  216 + }
  217 + }).catch(error => {
  218 + reject(error)
  219 + })
  220 + })
  221 +}
  222 +
  223 +// 更新物品类型
  224 +export function updateResourceStoreType(data) {
  225 + return new Promise((resolve, reject) => {
  226 + request({
  227 + url: '/resourceStoreType.updateResourceStoreType',
  228 + method: 'post',
  229 + data
  230 + }).then(response => {
  231 + const res = response.data
  232 + if (res.code === 0) {
  233 + resolve(res)
  234 + } else {
  235 + reject(new Error(res.msg || '更新物品类型失败'))
  236 + }
  237 + }).catch(error => {
  238 + reject(error)
  239 + })
  240 + })
  241 +}
  242 +
  243 +// 删除物品类型
  244 +export function deleteResourceStoreType(data) {
  245 + return new Promise((resolve, reject) => {
  246 + request({
  247 + url: '/resourceStoreType.deleteResourceStoreType',
  248 + method: 'post',
  249 + data
  250 + }).then(response => {
  251 + const res = response.data
  252 + if (res.code === 0) {
  253 + resolve(res)
  254 + } else {
  255 + reject(new Error(res.msg || '删除物品类型失败'))
  256 + }
  257 + }).catch(error => {
  258 + reject(error)
  259 + })
  260 + })
  261 +}
  262 +
  263 +// 上传文件
  264 +export function uploadFile(data) {
  265 + return new Promise((resolve, reject) => {
  266 + request({
  267 + url: '/uploadFile.uploadImage',
  268 + method: 'post',
  269 + data,
  270 + headers: {
  271 + 'Content-Type': 'multipart/form-data'
  272 + }
  273 + }).then(response => {
  274 + const res = response.data
  275 + if (res.code === 0) {
  276 + resolve(res)
  277 + } else {
  278 + reject(new Error(res.msg || '上传文件失败'))
  279 + }
  280 + }).catch(error => {
  281 + reject(error)
  282 + })
  283 + })
  284 +}
  285 +
  286 +// 获取物品类型树
  287 +export function listResourceStoreTypeTree() {
  288 + return new Promise((resolve, reject) => {
  289 + request({
  290 + url: '/resourceStore.listResourceStoreTypeTree',
  291 + method: 'get',
  292 + params: {
  293 + communityId: getCommunityId()
  294 + }
  295 + }).then(response => {
  296 + const res = response.data
  297 + if (res.code === 0) {
  298 + resolve(res)
  299 + } else {
  300 + reject(new Error(res.msg || '获取物品类型树失败'))
  301 + }
  302 + }).catch(error => {
  303 + reject(error)
  304 + })
  305 + })
  306 +}
0 307 \ No newline at end of file
... ...
src/components/resource/addResourceStore.vue 0 → 100644
  1 +<template>
  2 + <el-dialog :title="$t('resourceStoreManage.addResource')" :visible.sync="dialogVisible" width="70%"
  3 + :close-on-click-modal="false" @closed="handleClosed">
  4 + <el-form ref="addForm" :model="formData" :rules="rules" label-width="180px" label-position="right">
  5 + <el-row :gutter="20">
  6 + <el-col :span="12">
  7 + <el-form-item :label="$t('resourceStoreManage.resourceName')" prop="resName">
  8 + <el-input v-model.trim="formData.resName"
  9 + :placeholder="$t('resourceStoreManage.enterResourceName')"></el-input>
  10 + </el-form-item>
  11 + </el-col>
  12 + <el-col :span="12">
  13 + <el-form-item :label="$t('resourceStoreManage.resourceCode')" prop="resCode">
  14 + <el-input v-model.trim="formData.resCode"
  15 + :placeholder="$t('resourceStoreManage.enterResourceCode')"></el-input>
  16 + </el-form-item>
  17 + </el-col>
  18 +
  19 + <el-col :span="12">
  20 + <el-form-item :label="$t('resourceStoreManage.resourceType')" prop="parentRstId">
  21 + <el-select v-model="formData.parentRstId" style="width:100%" @change="handleResourceTypeChange">
  22 + <el-option :label="$t('resourceStoreManage.selectResourceType')" value="" disabled></el-option>
  23 + <el-option v-for="(item, index) in resourceStoreTypes" :key="index" :label="item.name"
  24 + :value="item.rstId"></el-option>
  25 + </el-select>
  26 + </el-form-item>
  27 + </el-col>
  28 + <el-col :span="12">
  29 + <el-form-item :label="$t('resourceStoreManage.secondCategory')" prop="rstId">
  30 + <el-select v-model="formData.rstId" style="width:100%" @change="handleSonResourceTypeChange">
  31 + <el-option :label="$t('resourceStoreManage.selectSecondCategory')" value="" disabled></el-option>
  32 + <el-option v-for="(item, index) in sonResourceStoreTypes" :key="index" :label="item.name"
  33 + :value="item.rstId"></el-option>
  34 + </el-select>
  35 + </el-form-item>
  36 + </el-col>
  37 +
  38 + <el-col :span="12">
  39 + <el-form-item :label="$t('resourceStoreManage.unit')" prop="unitCode">
  40 + <el-select v-model="formData.unitCode" style="width:100%">
  41 + <el-option :label="$t('resourceStoreManage.selectUnit')" value="" disabled></el-option>
  42 + <el-option v-for="(item, index) in unitCodes" :key="index" :label="item.name"
  43 + :value="item.statusCd"></el-option>
  44 + </el-select>
  45 + </el-form-item>
  46 + </el-col>
  47 + <el-col :span="12">
  48 + <el-form-item :label="$t('resourceStoreManage.fixedResource')" prop="isFixed">
  49 + <el-select v-model="formData.isFixed" style="width:100%">
  50 + <el-option :label="$t('resourceStoreManage.selectIsFixed')" value="" disabled></el-option>
  51 + <el-option v-for="(item, index) in isFixeds" :key="index" :label="item.name"
  52 + :value="item.statusCd"></el-option>
  53 + </el-select>
  54 + </el-form-item>
  55 + </el-col>
  56 +
  57 + <el-col :span="12">
  58 + <el-form-item :label="$t('resourceStoreManage.resourceSpec')" prop="rssId">
  59 + <el-select v-model="formData.rssId" style="width:100%">
  60 + <el-option :label="$t('resourceStoreManage.selectSpec')" value=""></el-option>
  61 + <el-option v-for="(item, index) in resourceStoreSpecifications" :key="index" :label="item.specName"
  62 + :value="item.rssId"></el-option>
  63 + </el-select>
  64 + </el-form-item>
  65 + </el-col>
  66 + <el-col :span="12">
  67 + <el-form-item :label="$t('resourceStoreManage.storehouse')" prop="shId">
  68 + <el-select v-model="formData.shId" style="width:100%">
  69 + <el-option :label="$t('resourceStoreManage.selectStorehouse')" value="" disabled></el-option>
  70 + <el-option v-for="(item, index) in storehouses" :key="index" :label="item.shName"
  71 + :value="item.shId"></el-option>
  72 + </el-select>
  73 + </el-form-item>
  74 + </el-col>
  75 +
  76 + <el-col :span="12">
  77 + <el-form-item :label="$t('resourceStoreManage.referencePrice')" prop="price">
  78 + <el-input v-model.trim="formData.price" :placeholder="$t('resourceStoreManage.enterReferencePrice')">
  79 + <template slot="prepend">¥</template>
  80 + </el-input>
  81 + </el-form-item>
  82 + </el-col>
  83 + <el-col :span="12">
  84 + <el-form-item :label="$t('resourceStoreManage.warningStock')" prop="warningStock">
  85 + <el-input v-model.trim="formData.warningStock"
  86 + :placeholder="$t('resourceStoreManage.enterWarningStock')"></el-input>
  87 + </el-form-item>
  88 + </el-col>
  89 +
  90 + <el-col :span="12">
  91 + <el-form-item :label="$t('resourceStoreManage.minUnit')" prop="miniUnitCode">
  92 + <el-select v-model="formData.miniUnitCode" style="width:100%">
  93 + <el-option :label="$t('resourceStoreManage.selectMinUnit')" value="" disabled></el-option>
  94 + <el-option v-for="(item, index) in unitCodes" :key="index" :label="item.name"
  95 + :value="item.statusCd"></el-option>
  96 + </el-select>
  97 + <div class="el-form-item__tip">
  98 + {{ $t('resourceStoreManage.minUnitTip') }}
  99 + </div>
  100 + </el-form-item>
  101 + </el-col>
  102 + <el-col :span="12">
  103 + <el-form-item :label="$t('resourceStoreManage.minUnitQty')" prop="miniUnitStock">
  104 + <el-input v-model.trim="formData.miniUnitStock"
  105 + :placeholder="$t('resourceStoreManage.enterMinUnitQty')"></el-input>
  106 + </el-form-item>
  107 + </el-col>
  108 +
  109 + <el-col :span="12">
  110 + <el-form-item :label="$t('resourceStoreManage.minCharge')" prop="outLowPrice">
  111 + <el-input v-model.trim="formData.outLowPrice" :placeholder="$t('resourceStoreManage.enterMinCharge')"
  112 + @change="validatePrices">
  113 + <template slot="prepend">¥</template>
  114 + </el-input>
  115 + </el-form-item>
  116 + </el-col>
  117 + <el-col :span="12">
  118 + <el-form-item :label="$t('resourceStoreManage.maxCharge')" prop="outHighPrice">
  119 + <el-input v-model.trim="formData.outHighPrice" :placeholder="$t('resourceStoreManage.enterMaxCharge')"
  120 + @change="validatePrices">
  121 + <template slot="prepend">¥</template>
  122 + </el-input>
  123 + </el-form-item>
  124 + </el-col>
  125 +
  126 + <el-col :span="12">
  127 + <el-form-item :label="$t('resourceStoreManage.initialStock')" prop="stock">
  128 + <el-input v-model.trim="formData.stock" :placeholder="$t('resourceStoreManage.enterInitialStock')"></el-input>
  129 + </el-form-item>
  130 + </el-col>
  131 + <el-col :span="12">
  132 + <el-form-item :label="$t('resourceStoreManage.remark')">
  133 + <el-input type="textarea" :placeholder="$t('resourceStoreManage.enterRemark')"
  134 + v-model.trim="formData.remark"></el-input>
  135 + </el-form-item>
  136 + </el-col>
  137 +
  138 + <el-col :span="12">
  139 + <el-form-item :label="$t('resourceStoreManage.description')">
  140 + <el-input type="textarea" :placeholder="$t('resourceStoreManage.enterDescription')"
  141 + v-model.trim="formData.description"></el-input>
  142 + </el-form-item>
  143 + </el-col>
  144 + <el-col :span="12">
  145 + <el-form-item :label="$t('resourceStoreManage.uploadImage')">
  146 + <upload-image-url ref="uploadImage" :image-count="5"
  147 + @notify-upload-image="handleImageUpload"></upload-image-url>
  148 + </el-form-item>
  149 + </el-col>
  150 + </el-row>
  151 + </el-form>
  152 +
  153 + <div slot="footer" class="dialog-footer">
  154 + <el-button @click="dialogVisible = false">{{ $t('common.cancel') }}</el-button>
  155 + <el-button type="primary" @click="saveResourceStore">{{ $t('common.save') }}</el-button>
  156 + </div>
  157 + </el-dialog>
  158 +</template>
  159 +
  160 +<script>
  161 +import { saveResourceStore,listResourceStoreSpecifications,listResourceStoreTypes,listStorehouses } from '@/api/resource/resourceStoreManageApi'
  162 +// import { listStorehouses } from '@/api/resource/resourceStoreApi'
  163 +// import { listResourceStoreTypes } from '@/api/resource/resourceStoreTypeApi'
  164 +
  165 +import { getDict, getCommunityId } from '@/api/community/communityApi'
  166 +import UploadImageUrl from '@/components/upload/UploadImageUrl'
  167 +
  168 +export default {
  169 + name: 'AddResourceStore',
  170 + components: {
  171 + UploadImageUrl
  172 + },
  173 + data() {
  174 + return {
  175 + dialogVisible: false,
  176 + formData: {
  177 + resName: '',
  178 + resCode: '',
  179 + parentRstId: '',
  180 + rstId: '',
  181 + rssId: '',
  182 + price: '',
  183 + description: '',
  184 + outLowPrice: '0',
  185 + outHighPrice: '0',
  186 + remark: '',
  187 + unitCode: '',
  188 + shId: '',
  189 + isFixed: 'N',
  190 + miniUnitCode: '1001',
  191 + miniUnitStock: '1',
  192 + warningStock: '10',
  193 + stock: '0',
  194 + photos: [],
  195 + communityId: getCommunityId()
  196 + },
  197 + resourceStoreTypes: [],
  198 + sonResourceStoreTypes: [],
  199 + resourceStoreSpecifications: [],
  200 + storehouses: [],
  201 + unitCodes: [],
  202 + isFixeds: [],
  203 + rules: {
  204 + resName: [
  205 + { required: true, message: this.$t('resourceStoreManage.resourceNameRequired'), trigger: 'blur' },
  206 + { min: 2, max: 100, message: this.$t('resourceStoreManage.resourceNameLength'), trigger: 'blur' }
  207 + ],
  208 + resCode: [
  209 + { required: true, message: this.$t('resourceStoreManage.resourceCodeRequired'), trigger: 'blur' },
  210 + { max: 50, message: this.$t('resourceStoreManage.resourceCodeMaxLength'), trigger: 'blur' }
  211 + ],
  212 + parentRstId: [
  213 + { required: true, message: this.$t('resourceStoreManage.resourceTypeRequired'), trigger: 'change' }
  214 + ],
  215 + rstId: [
  216 + { required: true, message: this.$t('resourceStoreManage.secondCategoryRequired'), trigger: 'change' }
  217 + ],
  218 + unitCode: [
  219 + { required: true, message: this.$t('resourceStoreManage.unitRequired'), trigger: 'change' }
  220 + ],
  221 + isFixed: [
  222 + { required: true, message: this.$t('resourceStoreManage.isFixedRequired'), trigger: 'change' }
  223 + ],
  224 + shId: [
  225 + { required: true, message: this.$t('resourceStoreManage.storehouseRequired'), trigger: 'change' }
  226 + ],
  227 + price: [
  228 + { required: true, message: this.$t('resourceStoreManage.referencePriceRequired'), trigger: 'blur' },
  229 + { pattern: /^\d+(\.\d{1,2})?$/, message: this.$t('resourceStoreManage.priceFormatError'), trigger: 'blur' }
  230 + ],
  231 + warningStock: [
  232 + { required: true, message: this.$t('resourceStoreManage.warningStockRequired'), trigger: 'blur' },
  233 + { pattern: /^[0-9]+$/, message: this.$t('resourceStoreManage.warningStockMin'), trigger: 'blur' }
  234 + ],
  235 + miniUnitCode: [
  236 + { required: true, message: this.$t('resourceStoreManage.minUnitRequired'), trigger: 'change' }
  237 + ],
  238 + miniUnitStock: [
  239 + { required: true, message: this.$t('resourceStoreManage.minUnitQtyRequired'), trigger: 'blur' }
  240 + ],
  241 + outLowPrice: [
  242 + { required: true, message: this.$t('resourceStoreManage.minChargeRequired'), trigger: 'blur' },
  243 + { pattern: /^\d+(\.\d{1,2})?$/, message: this.$t('resourceStoreManage.chargeFormatError'), trigger: 'blur' }
  244 + ],
  245 + outHighPrice: [
  246 + { required: true, message: this.$t('resourceStoreManage.maxChargeRequired'), trigger: 'blur' },
  247 + { pattern: /^\d+(\.\d{1,2})?$/, message: this.$t('resourceStoreManage.chargeFormatError'), trigger: 'blur' }
  248 + ],
  249 + stock: [
  250 + { required: true, message: this.$t('resourceStoreManage.initialStockRequired'), trigger: 'blur' }
  251 + ]
  252 + }
  253 + }
  254 + },
  255 + methods: {
  256 + open() {
  257 + this.dialogVisible = true
  258 + this.loadData()
  259 + },
  260 +
  261 + async loadData() {
  262 + await this.loadDictData()
  263 + await this.listResourceStoreTypes()
  264 + await this.listStorehouses()
  265 + },
  266 +
  267 + async loadDictData() {
  268 + try {
  269 + // 单位字典
  270 + const unitData = await getDict('resource_store', 'unit_code')
  271 + this.unitCodes = unitData || []
  272 +
  273 + // 是否固定物品字典
  274 + const fixedData = await getDict('resource_store', 'is_fixed')
  275 + this.isFixeds = fixedData || []
  276 + } catch (error) {
  277 + console.error('加载字典数据失败:', error)
  278 + }
  279 + },
  280 +
  281 + async listResourceStoreTypes() {
  282 + try {
  283 + const params = {
  284 + page: 1,
  285 + row: 100,
  286 + communityId: getCommunityId(),
  287 + parentId: '0'
  288 + }
  289 + const response = await listResourceStoreTypes(params)
  290 + this.resourceStoreTypes = response.data || []
  291 + } catch (error) {
  292 + console.error('加载物品类型失败:', error)
  293 + }
  294 + },
  295 +
  296 + async listStorehouses() {
  297 + try {
  298 + const params = {
  299 + page: 1,
  300 + row: 100,
  301 + communityId: getCommunityId()
  302 + }
  303 + const response = await listStorehouses(params)
  304 + this.storehouses = response.data || []
  305 + } catch (error) {
  306 + console.error('加载仓库列表失败:', error)
  307 + }
  308 + },
  309 +
  310 + handleResourceTypeChange(value) {
  311 + this.formData.rstId = ''
  312 + this.sonResourceStoreTypes = []
  313 + this.resourceStoreSpecifications = []
  314 +
  315 + if (!value) return
  316 +
  317 + this.listSonResourceStoreTypes(value)
  318 + },
  319 +
  320 + async listSonResourceStoreTypes(parentRstId) {
  321 + try {
  322 + const params = {
  323 + page: 1,
  324 + row: 100,
  325 + rstId: parentRstId,
  326 + flag: "0"
  327 + }
  328 + const response = await listResourceStoreTypes(params)
  329 + this.sonResourceStoreTypes = response.data || []
  330 + } catch (error) {
  331 + console.error('加载二级分类失败:', error)
  332 + }
  333 + },
  334 +
  335 + handleSonResourceTypeChange(value) {
  336 + if (!value) return
  337 + this.listResourceStoreSpecifications(value)
  338 + },
  339 +
  340 + async listResourceStoreSpecifications(rstId) {
  341 + try {
  342 + const params = {
  343 + page: 1,
  344 + row: 100,
  345 + rstId: rstId
  346 + }
  347 + const response = await listResourceStoreSpecifications(params)
  348 + this.resourceStoreSpecifications = response.data || []
  349 + } catch (error) {
  350 + console.error('加载物品规格失败:', error)
  351 + }
  352 + },
  353 +
  354 + validatePrices() {
  355 + const low = parseFloat(this.formData.outLowPrice)
  356 + const high = parseFloat(this.formData.outHighPrice)
  357 +
  358 + if (low > high) {
  359 + this.$message.error(this.$t('resourceStoreManage.maxChargeError'))
  360 + this.formData.outHighPrice = ''
  361 + }
  362 + },
  363 +
  364 + handleImageUpload(images) {
  365 + this.formData.photos = images.map(img => img.fileId)
  366 + },
  367 +
  368 + saveResourceStore() {
  369 + this.$refs.addForm.validate(async valid => {
  370 + if (valid) {
  371 + try {
  372 + await saveResourceStore(this.formData)
  373 + this.$message.success(this.$t('resourceStoreManage.addSuccess'))
  374 + this.dialogVisible = false
  375 + this.$emit('success')
  376 + } catch (error) {
  377 + console.error('添加物品失败:', error)
  378 + this.$message.error(error.message || this.$t('resourceStoreManage.addFailed'))
  379 + }
  380 + }
  381 + })
  382 + },
  383 +
  384 + handleClosed() {
  385 + this.$refs.addForm.resetFields()
  386 + this.$refs.uploadImage.clearImages()
  387 + this.formData = {
  388 + resName: '',
  389 + resCode: '',
  390 + parentRstId: '',
  391 + rstId: '',
  392 + rssId: '',
  393 + price: '',
  394 + description: '',
  395 + outLowPrice: '0',
  396 + outHighPrice: '0',
  397 + remark: '',
  398 + unitCode: '',
  399 + shId: '',
  400 + isFixed: 'N',
  401 + miniUnitCode: '1001',
  402 + miniUnitStock: '1',
  403 + warningStock: '10',
  404 + stock: '0',
  405 + photos: [],
  406 + communityId: getCommunityId()
  407 + }
  408 + this.sonResourceStoreTypes = []
  409 + this.resourceStoreSpecifications = []
  410 + }
  411 + }
  412 +}
  413 +</script>
  414 +
  415 +<style scoped>
  416 +.el-form-item__tip {
  417 + font-size: 12px;
  418 + color: #909399;
  419 + margin-top: 4px;
  420 +}
  421 +</style>
0 422 \ No newline at end of file
... ...
src/components/resource/addResourceStoreSpecification.vue
1 1 <template>
2   - <el-dialog
3   - :title="$t('resourceStoreSpecificationManage.addSpec')"
4   - :visible.sync="visible"
5   - width="50%"
  2 + <el-dialog :title="$t('resourceStoreSpecificationManage.addSpec')" :visible.sync="visible" width="50%"
6 3 @close="handleClose">
7   - <el-form
8   - :model="form"
9   - :rules="rules"
10   - ref="formRef"
11   - label-width="120px">
12   - <el-form-item
13   - :label="$t('resourceStoreSpecificationManage.specName')"
14   - prop="specName">
15   - <el-input
16   - v-model="form.specName"
17   - :placeholder="$t('resourceStoreSpecificationManage.specNamePlaceholder')">
  4 + <el-form :model="form" :rules="rules" ref="formRef" label-width="120px">
  5 + <el-form-item :label="$t('resourceStoreSpecificationManage.specName')" prop="specName">
  6 + <el-input v-model="form.specName" :placeholder="$t('resourceStoreSpecificationManage.specNamePlaceholder')">
18 7 </el-input>
19 8 </el-form-item>
20   -
21   - <el-form-item
22   - :label="$t('resourceStoreSpecificationManage.itemType')"
23   - prop="parentRstId"
  9 +
  10 + <el-form-item :label="$t('resourceStoreSpecificationManage.itemType')" prop="parentRstId"
24 11 class="item-type-form-item">
25 12 <el-col :span="11">
26   - <el-select
27   - v-model="form.parentRstId"
28   - :placeholder="$t('resourceStoreSpecificationManage.selectItemType')"
29   - @change="handleParentTypeChange"
30   - style="width:100%">
31   - <el-option
32   - v-for="item in resourceStoreTypes"
33   - :key="item.rstId"
34   - :label="item.name"
35   - :value="item.rstId">
  13 + <el-select v-model="form.parentRstId" :placeholder="$t('resourceStoreSpecificationManage.selectItemType')"
  14 + @change="handleParentTypeChange" style="width:100%">
  15 + <el-option v-for="item in resourceStoreTypes" :key="item.rstId" :label="item.name" :value="item.rstId">
36 16 </el-option>
37 17 </el-select>
38 18 </el-col>
39 19 <el-col :span="11" :offset="2">
40   - <el-select
41   - v-model="form.rstId"
42   - :placeholder="$t('resourceStoreSpecificationManage.selectSubCategory')"
  20 + <el-select v-model="form.rstId" :placeholder="$t('resourceStoreSpecificationManage.selectSubCategory')"
43 21 style="width:100%">
44   - <el-option
45   - v-for="item in sonResourceStoreTypes"
46   - :key="item.rstId"
47   - :label="item.name"
48   - :value="item.rstId">
  22 + <el-option v-for="item in sonResourceStoreTypes" :key="item.rstId" :label="item.name" :value="item.rstId">
49 23 </el-option>
50 24 </el-select>
51 25 </el-col>
52 26 </el-form-item>
53   -
54   - <el-form-item
55   - :label="$t('resourceStoreSpecificationManage.description')"
56   - prop="description">
57   - <el-input
58   - type="textarea"
59   - v-model="form.description"
60   - :placeholder="$t('resourceStoreSpecificationManage.descriptionPlaceholder')"
61   - :rows="3">
  27 +
  28 + <el-form-item :label="$t('resourceStoreSpecificationManage.description')" prop="description">
  29 + <el-input type="textarea" v-model="form.description"
  30 + :placeholder="$t('resourceStoreSpecificationManage.descriptionPlaceholder')" :rows="3">
62 31 </el-input>
63 32 </el-form-item>
64 33 </el-form>
65   -
  34 +
66 35 <div slot="footer" class="dialog-footer">
67 36 <el-button @click="visible = false">
68 37 {{ $t('resourceStoreSpecificationManage.cancel') }}
... ... @@ -112,7 +81,7 @@ export default {
112 81 this.visible = true
113 82 this.getResourceStoreTypes()
114 83 },
115   -
  84 +
116 85 async getResourceStoreTypes() {
117 86 try {
118 87 const params = {
... ... @@ -120,14 +89,14 @@ export default {
120 89 row: 100,
121 90 parentId: '0'
122 91 }
123   -
  92 +
124 93 const res = await listResourceStoreTypes(params)
125 94 this.resourceStoreTypes = res.data
126 95 } catch (error) {
127 96 console.error('Failed to get item types:', error)
128 97 }
129 98 },
130   -
  99 +
131 100 async getResourceStoreSonTypes(parentRstId) {
132 101 try {
133 102 const params = {
... ... @@ -136,14 +105,14 @@ export default {
136 105 rstId: parentRstId,
137 106 flag: "0"
138 107 }
139   -
  108 +
140 109 const res = await listResourceStoreTypes(params)
141 110 this.sonResourceStoreTypes = res.data
142 111 } catch (error) {
143 112 console.error('Failed to get sub item types:', error)
144 113 }
145 114 },
146   -
  115 +
147 116 handleParentTypeChange(val) {
148 117 this.form.rstId = ''
149 118 if (!val) {
... ... @@ -152,7 +121,7 @@ export default {
152 121 }
153 122 this.getResourceStoreSonTypes(val)
154 123 },
155   -
  124 +
156 125 submitForm() {
157 126 this.$refs.formRef.validate(async valid => {
158 127 if (valid) {
... ... @@ -168,7 +137,7 @@ export default {
168 137 }
169 138 })
170 139 },
171   -
  140 +
172 141 handleClose() {
173 142 this.$refs.formRef.resetFields()
174 143 this.form = {
... ...
src/components/resource/addResourceStoreType.vue 0 → 100644
  1 +<template>
  2 + <el-dialog
  3 + :title="dialogTitle"
  4 + :visible.sync="dialogVisible"
  5 + width="40%"
  6 + :close-on-click-modal="false"
  7 + @closed="handleClosed"
  8 + >
  9 + <el-form
  10 + ref="addForm"
  11 + :model="formData"
  12 + :rules="rules"
  13 + label-width="120px"
  14 + label-position="right"
  15 + >
  16 + <el-form-item :label="$t('resourceStoreManage.typeName')" prop="name">
  17 + <el-input
  18 + v-model.trim="formData.name"
  19 + :placeholder="$t('resourceStoreManage.enterTypeName')"
  20 + maxlength="20"
  21 + ></el-input>
  22 + </el-form-item>
  23 +
  24 + <el-form-item :label="$t('resourceStoreManage.description')">
  25 + <el-input
  26 + type="textarea"
  27 + :placeholder="$t('resourceStoreManage.enterTypeDescription')"
  28 + v-model.trim="formData.description"
  29 + ></el-input>
  30 + </el-form-item>
  31 + </el-form>
  32 +
  33 + <div slot="footer" class="dialog-footer">
  34 + <el-button @click="dialogVisible = false">{{ $t('common.cancel') }}</el-button>
  35 + <el-button type="primary" @click="saveResourceStoreType" :loading="saving">
  36 + {{ $t('common.save') }}
  37 + </el-button>
  38 + </div>
  39 + </el-dialog>
  40 +</template>
  41 +
  42 +<script>
  43 +import { saveResourceStoreType } from '@/api/resource/resourceStoreManageApi'
  44 +import { getCommunityId } from '@/api/community/communityApi'
  45 +
  46 +export default {
  47 + name: 'AddResourceStoreType',
  48 + data() {
  49 + return {
  50 + dialogVisible: false,
  51 + saving: false,
  52 + level: 1,
  53 + formData: {
  54 + name: '',
  55 + description: '',
  56 + parentId: '0',
  57 + communityId: getCommunityId()
  58 + },
  59 + rules: {
  60 + name: [
  61 + { required: true, message: this.$t('resourceStoreManage.typeNameRequired'), trigger: 'blur' }
  62 + ]
  63 + }
  64 + }
  65 + },
  66 + computed: {
  67 + dialogTitle() {
  68 + return this.level === 1
  69 + ? this.$t('resourceStoreManage.addFirstLevelType')
  70 + : this.$t('resourceStoreManage.addSecondLevelType')
  71 + }
  72 + },
  73 + methods: {
  74 + open(rstId) {
  75 + if(rstId){
  76 + this.formData.parentId = rstId
  77 + }
  78 + this.dialogVisible = true
  79 + },
  80 +
  81 + async saveResourceStoreType() {
  82 + this.$refs.addForm.validate(async valid => {
  83 + if (valid) {
  84 + try {
  85 + this.saving = true
  86 + await saveResourceStoreType(this.formData)
  87 + this.$message.success(this.$t('resourceStoreManage.addTypeSuccess'))
  88 + this.dialogVisible = false
  89 + this.$emit('success')
  90 + } catch (error) {
  91 + console.error('添加物品类型失败:', error)
  92 + this.$message.error(this.$t('resourceStoreManage.addTypeFailed'))
  93 + } finally {
  94 + this.saving = false
  95 + }
  96 + }
  97 + })
  98 + },
  99 +
  100 + handleClosed() {
  101 + this.$refs.addForm.resetFields()
  102 + this.formData = {
  103 + name: '',
  104 + description: '',
  105 + parentId: '0',
  106 + communityId: getCommunityId()
  107 + }
  108 + }
  109 + }
  110 +}
  111 +</script>
  112 +
  113 +<style scoped>
  114 +.el-form-item__content {
  115 + margin-left: 0 !important;
  116 +}
  117 +</style>
0 118 \ No newline at end of file
... ...
src/components/resource/deleteResourceStore.vue 0 → 100644
  1 +<template>
  2 + <el-dialog
  3 + :title="$t('resourceStoreManage.confirmOperation')"
  4 + :visible.sync="dialogVisible"
  5 + width="30%"
  6 + :close-on-click-modal="false"
  7 + >
  8 + <div class="confirm-content">
  9 + <p>{{ $t('resourceStoreManage.confirmDeleteResource') }}</p>
  10 + </div>
  11 +
  12 + <div slot="footer" class="dialog-footer">
  13 + <el-button @click="dialogVisible = false">
  14 + {{ $t('resourceStoreManage.cancelDelete') }}
  15 + </el-button>
  16 + <el-button type="primary" @click="confirmDelete">
  17 + {{ $t('resourceStoreManage.confirmDelete') }}
  18 + </el-button>
  19 + </div>
  20 + </el-dialog>
  21 +</template>
  22 +
  23 +<script>
  24 +import { deleteResourceStore } from '@/api/resource/resourceStoreManageApi'
  25 +import { getCommunityId } from '@/api/community/communityApi'
  26 +
  27 +export default {
  28 + name: 'DeleteResourceStore',
  29 + data() {
  30 + return {
  31 + dialogVisible: false,
  32 + resourceData: null
  33 + }
  34 + },
  35 + methods: {
  36 + open(resource) {
  37 + this.resourceData = { ...resource }
  38 + this.dialogVisible = true
  39 + },
  40 +
  41 + async confirmDelete() {
  42 + if (!this.resourceData) return
  43 +
  44 + try {
  45 + const params = {
  46 + ...this.resourceData,
  47 + communityId: getCommunityId()
  48 + }
  49 + await deleteResourceStore(params)
  50 + this.$message.success(this.$t('resourceStoreManage.deleteSuccess'))
  51 + this.dialogVisible = false
  52 + this.$emit('success')
  53 + } catch (error) {
  54 + console.error('删除物品失败:', error)
  55 + this.$message.error(this.$t('resourceStoreManage.deleteFailed'))
  56 + }
  57 + }
  58 + }
  59 +}
  60 +</script>
  61 +
  62 +<style scoped>
  63 +.confirm-content {
  64 + text-align: center;
  65 + font-size: 16px;
  66 + margin: 20px 0;
  67 +}
  68 +</style>
0 69 \ No newline at end of file
... ...
src/components/resource/deleteResourceStoreType.vue 0 → 100644
  1 +<template>
  2 + <el-dialog
  3 + id="deleteResourceStoreTypeModel"
  4 + :title="$t('deleteResourceStoreType.confirmTitle')"
  5 + :visible.sync="visible"
  6 + width="30%"
  7 + :before-close="handleClose"
  8 + >
  9 + <div style="text-align: center;">
  10 + <span>{{ $t('deleteResourceStoreType.confirmMessage') }}</span>
  11 + </div>
  12 + <span slot="footer" class="dialog-footer">
  13 + <el-button @click="handleClose">{{ $t('deleteResourceStoreType.cancel') }}</el-button>
  14 + <el-button type="primary" @click="deleteResourceStoreType">{{ $t('deleteResourceStoreType.confirm') }}</el-button>
  15 + </span>
  16 + </el-dialog>
  17 +</template>
  18 +
  19 +<script>
  20 +import { deleteResourceStoreType } from '@/api/resource/resourceStoreManageApi'
  21 +import { getCommunityId } from '@/api/community/communityApi'
  22 +
  23 +export default {
  24 + name: 'DeleteResourceStoreType',
  25 + data() {
  26 + return {
  27 + visible: false,
  28 + deleteResourceStoreTypeInfo: {}
  29 + }
  30 + },
  31 + methods: {
  32 + open(resourceStoreType) {
  33 + this.visible = true
  34 + this.deleteResourceStoreTypeInfo = resourceStoreType
  35 + },
  36 + handleClose() {
  37 + this.visible = false
  38 + this.deleteResourceStoreTypeInfo = {}
  39 + },
  40 + async deleteResourceStoreType() {
  41 + this.deleteResourceStoreTypeInfo.communityId = getCommunityId()
  42 + try {
  43 + const response = await deleteResourceStoreType(this.deleteResourceStoreTypeInfo)
  44 + if (response.code === 0) {
  45 + this.$message.success(this.$t('common.deleteSuccess'))
  46 + this.handleClose()
  47 + this.$emit('success')
  48 + } else {
  49 + this.$message.error(response.msg)
  50 + }
  51 + } catch (error) {
  52 + this.$message.error(this.$t('common.deleteFailed'))
  53 + }
  54 + }
  55 + }
  56 +}
  57 +</script>
  58 +
  59 +<style scoped>
  60 +</style>
0 61 \ No newline at end of file
... ...
src/components/resource/editResourceStore.vue 0 → 100644
  1 +<template>
  2 + <el-dialog :title="$t('resourceStoreManage.editResource')" :visible.sync="dialogVisible" width="70%"
  3 + :close-on-click-modal="false" @closed="handleClosed">
  4 + <el-form ref="editForm" :model="formData" :rules="rules" label-width="180px" label-position="right">
  5 + <el-row :gutter="20">
  6 + <el-col :span="12">
  7 + <el-form-item :label="$t('resourceStoreManage.resourceName')" prop="resName">
  8 + <el-input v-model.trim="formData.resName" :placeholder="$t('resourceStoreManage.enterResourceName')"
  9 + :disabled="formData.shType === '2807'"></el-input>
  10 + </el-form-item>
  11 + </el-col>
  12 + <el-col :span="12">
  13 + <el-form-item :label="$t('resourceStoreManage.resourceCode')" prop="resCode">
  14 + <el-input v-model.trim="formData.resCode" :placeholder="$t('resourceStoreManage.enterResourceCode')"
  15 + disabled></el-input>
  16 + </el-form-item>
  17 + </el-col>
  18 +
  19 + <el-col :span="12">
  20 + <el-form-item :label="$t('resourceStoreManage.resourceType')" prop="parentRstId">
  21 + <el-select v-model="formData.parentRstId" style="width:100%" :disabled="formData.shType === '2807'"
  22 + @change="handleResourceTypeChange">
  23 + <el-option v-for="(item, index) in parentRstIds" :key="index" :label="item.name"
  24 + :value="item.rstId"></el-option>
  25 + </el-select>
  26 + </el-form-item>
  27 + </el-col>
  28 + <el-col :span="12">
  29 + <el-form-item :label="$t('resourceStoreManage.secondCategory')" prop="rstId">
  30 + <el-select v-model="formData.rstId" style="width:100%" :disabled="formData.shType === '2807'"
  31 + @change="handleSonResourceTypeChange">
  32 + <el-option :label="$t('resourceStoreManage.selectSecondCategory')" value="" disabled></el-option>
  33 + <el-option v-for="(item, index) in rstIds" :key="index" :label="item.name" :value="item.rstId"></el-option>
  34 + </el-select>
  35 + </el-form-item>
  36 + </el-col>
  37 +
  38 + <el-col :span="12">
  39 + <el-form-item :label="$t('resourceStoreManage.resourceSpec')" prop="rssId">
  40 + <el-select v-model="formData.rssId" style="width:100%" :disabled="formData.shType === '2807'">
  41 + <el-option :label="$t('resourceStoreManage.selectSpec')" value=""></el-option>
  42 + <el-option v-for="(item, index) in resourceStoreSpecifications" :key="index" :label="item.specName"
  43 + :value="item.rssId"></el-option>
  44 + </el-select>
  45 + </el-form-item>
  46 + </el-col>
  47 + <el-col :span="12">
  48 + <el-form-item :label="$t('resourceStoreManage.unit')" prop="unitCode">
  49 + <el-select v-model="formData.unitCode" style="width:100%" :disabled="formData.shType === '2807'">
  50 + <el-option v-for="(item, index) in unitCodes" :key="index" :label="item.name"
  51 + :value="item.statusCd"></el-option>
  52 + </el-select>
  53 + </el-form-item>
  54 + </el-col>
  55 +
  56 + <el-col :span="12">
  57 + <el-form-item :label="$t('resourceStoreManage.fixedResource')" prop="isFixed">
  58 + <el-select v-model="formData.isFixed" style="width:100%">
  59 + <el-option :label="$t('resourceStoreManage.selectIsFixed')" value="" disabled></el-option>
  60 + <el-option v-for="(item, index) in isFixeds" :key="index" :label="item.name"
  61 + :value="item.statusCd"></el-option>
  62 + </el-select>
  63 + </el-form-item>
  64 + </el-col>
  65 + <el-col :span="12">
  66 + <el-form-item :label="$t('resourceStoreManage.referencePrice')" prop="price">
  67 + <el-input v-model.trim="formData.price" :placeholder="$t('resourceStoreManage.enterReferencePrice')"
  68 + :disabled="formData.shType === '2807'">
  69 + <template slot="prepend">¥</template>
  70 + </el-input>
  71 + </el-form-item>
  72 + </el-col>
  73 +
  74 + <el-col :span="12">
  75 + <el-form-item :label="$t('resourceStoreManage.warningStock')" prop="warningStock">
  76 + <el-input v-model.trim="formData.warningStock"
  77 + :placeholder="$t('resourceStoreManage.enterWarningStock')"></el-input>
  78 + </el-form-item>
  79 + </el-col>
  80 + <el-col :span="12">
  81 + <el-form-item :label="$t('resourceStoreManage.minUnit')" prop="miniUnitCode">
  82 + <el-select v-model="formData.miniUnitCode" style="width:100%" :disabled="formData.shType === '2807'">
  83 + <el-option :label="$t('resourceStoreManage.selectMinUnit')" value="" disabled></el-option>
  84 + <el-option v-for="(item, index) in unitCodes" :key="index" :label="item.name"
  85 + :value="item.statusCd"></el-option>
  86 + </el-select>
  87 + <div class="el-form-item__tip" v-if="formData.shType !== '2807'">
  88 + {{ $t('resourceStoreManage.minUnitTip') }}
  89 + </div>
  90 + </el-form-item>
  91 + </el-col>
  92 +
  93 + <el-col :span="12">
  94 + <el-form-item :label="$t('resourceStoreManage.minUnitQty')" prop="miniUnitStock">
  95 + <el-input v-model.trim="formData.miniUnitStock" :placeholder="$t('resourceStoreManage.enterMinUnitQty')"
  96 + :disabled="formData.shType === '2807'"></el-input>
  97 + </el-form-item>
  98 + </el-col>
  99 + <el-col :span="12">
  100 + <el-form-item :label="$t('resourceStoreManage.minCharge')" prop="outLowPrice">
  101 + <el-input v-model.trim="formData.outLowPrice" :placeholder="$t('resourceStoreManage.enterMinCharge')"
  102 + @change="validatePrices">
  103 + <template slot="prepend">¥</template>
  104 + </el-input>
  105 + </el-form-item>
  106 + </el-col>
  107 +
  108 + <el-col :span="12">
  109 + <el-form-item :label="$t('resourceStoreManage.maxCharge')" prop="outHighPrice">
  110 + <el-input v-model.trim="formData.outHighPrice" :placeholder="$t('resourceStoreManage.enterMaxCharge')"
  111 + @change="validatePrices">
  112 + <template slot="prepend">¥</template>
  113 + </el-input>
  114 + </el-form-item>
  115 + </el-col>
  116 + <el-col :span="12">
  117 + <el-form-item :label="$t('resourceStoreManage.remark')">
  118 + <el-input type="textarea" :placeholder="$t('resourceStoreManage.enterRemark')"
  119 + v-model.trim="formData.remark"></el-input>
  120 + </el-form-item>
  121 + </el-col>
  122 +
  123 + <el-col :span="12">
  124 + <el-form-item :label="$t('resourceStoreManage.description')">
  125 + <el-input type="textarea" :placeholder="$t('resourceStoreManage.enterDescription')"
  126 + v-model.trim="formData.description"></el-input>
  127 + </el-form-item>
  128 + </el-col>
  129 + <el-col :span="12">
  130 + <el-form-item :label="$t('resourceStoreManage.images')">
  131 + <upload-image-url ref="uploadImage" :image-count="5"
  132 + @notify-upload-image="handleImageUpload"></upload-image-url>
  133 + </el-form-item>
  134 + </el-col>
  135 + </el-row>
  136 + </el-form>
  137 +
  138 + <div slot="footer" class="dialog-footer">
  139 + <el-button @click="dialogVisible = false">{{ $t('common.cancel') }}</el-button>
  140 + <el-button type="primary" @click="updateResourceStore">{{ $t('common.save') }}</el-button>
  141 + </div>
  142 + </el-dialog>
  143 +</template>
  144 +
  145 +<script>
  146 +import { updateResourceStore ,listStorehouses,listResourceStoreTypes, getResourceStoreType,listResourceStoreSpecifications} from '@/api/resource/resourceStoreManageApi'
  147 +import { getDict, getCommunityId } from '@/api/community/communityApi'
  148 +import UploadImageUrl from '@/components/upload/UploadImageUrl'
  149 +
  150 +export default {
  151 + name: 'EditResourceStore',
  152 + components: {
  153 + UploadImageUrl
  154 + },
  155 + data() {
  156 + return {
  157 + dialogVisible: false,
  158 + formData: {
  159 + resId: '',
  160 + resName: '',
  161 + resCode: '',
  162 + parentRstId: '',
  163 + rstId: '',
  164 + rssId: '',
  165 + price: '',
  166 + description: '',
  167 + outLowPrice: '0',
  168 + outHighPrice: '0',
  169 + remark: '',
  170 + unitCode: '',
  171 + miniUnitCode: '',
  172 + miniUnitStock: '',
  173 + warningStock: '',
  174 + isFixed: '',
  175 + shType: '',
  176 + fileUrls: [],
  177 + communityId: getCommunityId()
  178 + },
  179 + parentRstIds: [],
  180 + rstIds: [],
  181 + resourceStoreSpecifications: [],
  182 + storehouses: [],
  183 + unitCodes: [],
  184 + isFixeds: [],
  185 + rules: {
  186 + resName: [
  187 + { required: true, message: this.$t('resourceStoreManage.resourceNameRequired'), trigger: 'blur' },
  188 + { min: 2, max: 100, message: this.$t('resourceStoreManage.resourceNameLength'), trigger: 'blur' }
  189 + ],
  190 + resCode: [
  191 + { required: true, message: this.$t('resourceStoreManage.resourceCodeRequired'), trigger: 'blur' },
  192 + { max: 50, message: this.$t('resourceStoreManage.resourceCodeMaxLength'), trigger: 'blur' }
  193 + ],
  194 + parentRstId: [
  195 + { required: true, message: this.$t('resourceStoreManage.resourceTypeRequired'), trigger: 'change' }
  196 + ],
  197 + rstId: [
  198 + { required: true, message: this.$t('resourceStoreManage.secondCategoryRequired'), trigger: 'change' }
  199 + ],
  200 + unitCode: [
  201 + { required: true, message: this.$t('resourceStoreManage.unitRequired'), trigger: 'change' }
  202 + ],
  203 + isFixed: [
  204 + { required: true, message: this.$t('resourceStoreManage.isFixedRequired'), trigger: 'change' }
  205 + ],
  206 + price: [
  207 + { required: true, message: this.$t('resourceStoreManage.referencePriceRequired'), trigger: 'blur' },
  208 + { pattern: /^\d+(\.\d{1,2})?$/, message: this.$t('resourceStoreManage.priceFormatError'), trigger: 'blur' }
  209 + ],
  210 + warningStock: [
  211 + { required: true, message: this.$t('resourceStoreManage.warningStockRequired'), trigger: 'blur' }
  212 + ],
  213 + miniUnitCode: [
  214 + { required: true, message: this.$t('resourceStoreManage.minUnitRequired'), trigger: 'change' }
  215 + ],
  216 + miniUnitStock: [
  217 + { required: true, message: this.$t('resourceStoreManage.minUnitQtyRequired'), trigger: 'blur' }
  218 + ],
  219 + outLowPrice: [
  220 + { required: true, message: this.$t('resourceStoreManage.minChargeRequired'), trigger: 'blur' },
  221 + { pattern: /^\d+(\.\d{1,2})?$/, message: this.$t('resourceStoreManage.chargeFormatError'), trigger: 'blur' }
  222 + ],
  223 + outHighPrice: [
  224 + { required: true, message: this.$t('resourceStoreManage.maxChargeRequired'), trigger: 'blur' },
  225 + { pattern: /^\d+(\.\d{1,2})?$/, message: this.$t('resourceStoreManage.chargeFormatError'), trigger: 'blur' }
  226 + ]
  227 + }
  228 + }
  229 + },
  230 + methods: {
  231 + open(row) {
  232 + this.dialogVisible = true
  233 + this.formData = { ...row }
  234 + this.$nextTick(() => {
  235 + if (this.$refs.uploadImage) {
  236 + this.$refs.uploadImage.setPhotos(row.fileUrls || [])
  237 + }
  238 + })
  239 + this.loadData()
  240 + },
  241 +
  242 + async loadData() {
  243 + await this.loadDictData()
  244 + await this.listResourceStoreTypes()
  245 + await this.listStorehouses()
  246 + await this.loadResourceStoreType()
  247 + await this.listSonResourceStoreTypes()
  248 + await this.listResourceStoreSpecifications()
  249 + },
  250 +
  251 + async loadDictData() {
  252 + try {
  253 + // 单位字典
  254 + const unitData = await getDict('resource_store', 'unit_code')
  255 + this.unitCodes = unitData || []
  256 +
  257 + // 是否固定物品字典
  258 + const fixedData = await getDict('resource_store', 'is_fixed')
  259 + this.isFixeds = fixedData || []
  260 + } catch (error) {
  261 + console.error('加载字典数据失败:', error)
  262 + }
  263 + },
  264 +
  265 + async listResourceStoreTypes() {
  266 + try {
  267 + const params = {
  268 + page: 1,
  269 + row: 100,
  270 + communityId: getCommunityId(),
  271 + parentId: '0'
  272 + }
  273 + const response = await listResourceStoreTypes(params)
  274 + this.parentRstIds = response.data || []
  275 + } catch (error) {
  276 + console.error('加载物品类型失败:', error)
  277 + }
  278 + },
  279 +
  280 + async loadResourceStoreType() {
  281 + if (!this.formData.parentRstId) return
  282 +
  283 + try {
  284 + const response = await getResourceStoreType(this.formData.parentRstId)
  285 + if (response.data) {
  286 + this.formData.parentRstId = response.data.rstId
  287 + }
  288 + } catch (error) {
  289 + console.error('加载物品类型详情失败:', error)
  290 + }
  291 + },
  292 +
  293 + async listSonResourceStoreTypes() {
  294 + if (!this.formData.parentRstId) return
  295 +
  296 + try {
  297 + const params = {
  298 + page: 1,
  299 + row: 100,
  300 + rstId: this.formData.parentRstId,
  301 + flag: "0"
  302 + }
  303 + const response = await listResourceStoreTypes(params)
  304 + this.rstIds = response.data || []
  305 + } catch (error) {
  306 + console.error('加载二级分类失败:', error)
  307 + }
  308 + },
  309 +
  310 + async listStorehouses() {
  311 + try {
  312 + const params = {
  313 + page: 1,
  314 + row: 100,
  315 + communityId: getCommunityId()
  316 + }
  317 + const response = await listStorehouses(params)
  318 + this.storehouses = response.data || []
  319 + } catch (error) {
  320 + console.error('加载仓库列表失败:', error)
  321 + }
  322 + },
  323 +
  324 + handleResourceTypeChange(value) {
  325 + this.formData.rstId = ''
  326 + this.rstIds = []
  327 + this.resourceStoreSpecifications = []
  328 +
  329 + if (!value) return
  330 +
  331 + this.listSonResourceStoreTypes(value)
  332 + },
  333 +
  334 + handleSonResourceTypeChange(value) {
  335 + if (!value) return
  336 + this.listResourceStoreSpecifications(value)
  337 + },
  338 +
  339 + async listResourceStoreSpecifications(rstId) {
  340 + try {
  341 + const params = {
  342 + page: 1,
  343 + row: 100,
  344 + rstId: rstId
  345 + }
  346 + const response = await listResourceStoreSpecifications(params)
  347 + this.resourceStoreSpecifications = response.data || []
  348 + } catch (error) {
  349 + console.error('加载物品规格失败:', error)
  350 + }
  351 + },
  352 +
  353 + validatePrices() {
  354 + const low = parseFloat(this.formData.outLowPrice)
  355 + const high = parseFloat(this.formData.outHighPrice)
  356 +
  357 + if (low > high) {
  358 + this.$message.error(this.$t('resourceStoreManage.maxChargeError'))
  359 + this.formData.outHighPrice = ''
  360 + }
  361 + },
  362 +
  363 + handleImageUpload(images) {
  364 + this.formData.fileUrls = images.map(img => ({ fileId: img.fileId, url: img.url }))
  365 + },
  366 +
  367 + updateResourceStore() {
  368 + this.$refs.editForm.validate(async valid => {
  369 + if (valid) {
  370 + try {
  371 + await updateResourceStore(this.formData)
  372 + this.$message.success(this.$t('resourceStoreManage.updateSuccess'))
  373 + this.dialogVisible = false
  374 + this.$emit('success')
  375 + } catch (error) {
  376 + console.error('更新物品失败:', error)
  377 + this.$message.error(error.message || this.$t('resourceStoreManage.updateFailed'))
  378 + }
  379 + }
  380 + })
  381 + },
  382 +
  383 + handleClosed() {
  384 + this.$refs.editForm.resetFields()
  385 + if (this.$refs.uploadImage) {
  386 + this.$refs.uploadImage.clearImages()
  387 + }
  388 + this.formData = {
  389 + resId: '',
  390 + resName: '',
  391 + resCode: '',
  392 + parentRstId: '',
  393 + rstId: '',
  394 + rssId: '',
  395 + price: '',
  396 + description: '',
  397 + outLowPrice: '0',
  398 + outHighPrice: '0',
  399 + remark: '',
  400 + unitCode: '',
  401 + miniUnitCode: '',
  402 + miniUnitStock: '',
  403 + warningStock: '',
  404 + isFixed: '',
  405 + shType: '',
  406 + fileUrls: [],
  407 + communityId: getCommunityId()
  408 + }
  409 + this.rstIds = []
  410 + this.resourceStoreSpecifications = []
  411 + }
  412 + }
  413 +}
  414 +</script>
  415 +
  416 +<style scoped>
  417 +.el-form-item__tip {
  418 + font-size: 12px;
  419 + color: #909399;
  420 + margin-top: 4px;
  421 +}
  422 +</style>
0 423 \ No newline at end of file
... ...
src/components/resource/editResourceStoreType.vue 0 → 100644
  1 +<template>
  2 + <el-dialog :title="$t('resourceStoreManage.editResourceType')" :visible.sync="dialogVisible" width="40%"
  3 + :close-on-click-modal="false" @closed="handleClosed">
  4 + <el-form ref="editForm" :model="formData" :rules="rules" label-width="120px" label-position="right">
  5 + <el-form-item :label="$t('resourceStoreManage.typeName')" prop="name">
  6 + <el-input v-model.trim="formData.name" :placeholder="$t('resourceStoreManage.enterTypeName')"></el-input>
  7 + </el-form-item>
  8 +
  9 + <el-form-item :label="$t('resourceStoreManage.description')">
  10 + <el-input type="textarea" :placeholder="$t('resourceStoreManage.enterTypeDescription')"
  11 + v-model.trim="formData.description"></el-input>
  12 + </el-form-item>
  13 + </el-form>
  14 +
  15 + <div slot="footer" class="dialog-footer">
  16 + <el-button @click="dialogVisible = false">{{ $t('common.cancel') }}</el-button>
  17 + <el-button type="primary" @click="updateResourceStoreType" :loading="saving">
  18 + {{ $t('common.save') }}
  19 + </el-button>
  20 + </div>
  21 + </el-dialog>
  22 +</template>
  23 +
  24 +<script>
  25 +import { updateResourceStoreType } from '@/api/resource/resourceStoreManageApi'
  26 +import { getCommunityId } from '@/api/community/communityApi'
  27 +
  28 +export default {
  29 + name: 'EditResourceStoreType',
  30 + data() {
  31 + return {
  32 + dialogVisible: false,
  33 + saving: false,
  34 + formData: {
  35 + rstId: '',
  36 + name: '',
  37 + description: '',
  38 + communityId: getCommunityId()
  39 + },
  40 + rules: {
  41 + name: [
  42 + { required: true, message: this.$t('resourceStoreManage.typeNameRequired'), trigger: 'blur' }
  43 + ]
  44 + }
  45 + }
  46 + },
  47 + methods: {
  48 + open(typeData) {
  49 + if (typeData) {
  50 + this.formData = {
  51 + rstId: typeData.rstId,
  52 + name: typeData.name,
  53 + parentId: typeData.parentId,
  54 + description: typeData.description || '',
  55 + communityId: getCommunityId()
  56 + }
  57 + }
  58 + this.dialogVisible = true
  59 + },
  60 +
  61 + async updateResourceStoreType() {
  62 + this.$refs.editForm.validate(async valid => {
  63 + if (valid) {
  64 + try {
  65 + this.saving = true
  66 + await updateResourceStoreType(this.formData)
  67 + this.$message.success(this.$t('resourceStoreManage.updateTypeSuccess'))
  68 + this.dialogVisible = false
  69 + this.$emit('success')
  70 + } catch (error) {
  71 + console.error('更新物品类型失败:', error)
  72 + this.$message.error(this.$t('resourceStoreManage.updateTypeFailed'))
  73 + } finally {
  74 + this.saving = false
  75 + }
  76 + }
  77 + })
  78 + },
  79 +
  80 + handleClosed() {
  81 + this.$refs.editForm.resetFields()
  82 + this.formData = {
  83 + rstId: '',
  84 + name: '',
  85 + description: '',
  86 + communityId: getCommunityId()
  87 + }
  88 + }
  89 + }
  90 +}
  91 +</script>
  92 +
  93 +<style scoped>
  94 +.el-form-item__content {
  95 + margin-left: 0 !important;
  96 +}
  97 +</style>
0 98 \ No newline at end of file
... ...
src/components/resource/importResourceStore.vue 0 → 100644
  1 +<template>
  2 + <el-dialog :title="$t('resourceStoreManage.importResource')" :visible.sync="dialogVisible" width="40%"
  3 + :close-on-click-modal="false" @closed="handleClosed">
  4 + <el-form ref="importForm" :model="formData" :rules="rules" label-width="120px" label-position="right">
  5 + <el-form-item :label="$t('resourceStoreManage.storehouse')" prop="shId">
  6 + <el-select v-model="formData.shId" style="width:100%">
  7 + <el-option :label="$t('resourceStoreManage.selectStorehouse')" value="" disabled></el-option>
  8 + <el-option v-for="(item, index) in storehouses" :key="index" :label="item.shName"
  9 + :value="item.shId"></el-option>
  10 + </el-select>
  11 + </el-form-item>
  12 +
  13 + <el-form-item :label="$t('resourceStoreManage.selectFile')" prop="file">
  14 + <el-upload class="upload-demo" action="" :auto-upload="false" :on-change="handleFileChange"
  15 + :show-file-list="false">
  16 + <el-button size="small" type="primary">
  17 + {{ $t('resourceStoreManage.browse') }}
  18 + </el-button>
  19 + <div slot="tip" class="el-upload__tip">
  20 + {{ fileName || $t('resourceStoreManage.selectDataFile') }}
  21 + </div>
  22 + </el-upload>
  23 + </el-form-item>
  24 +
  25 + <el-form-item :label="$t('resourceStoreManage.downloadTemplate')">
  26 + <div>
  27 + {{ $t('resourceStoreManage.downloadTemplateTip1') }}
  28 + <a href="/import/importResourceStore.xlsx" target="_blank">
  29 + {{ $t('resourceStoreManage.resourceTemplate') }}
  30 + </a>
  31 + {{ $t('resourceStoreManage.downloadTemplateTip2') }}
  32 + </div>
  33 + </el-form-item>
  34 + </el-form>
  35 +
  36 + <div slot="footer" class="dialog-footer">
  37 + <el-button @click="dialogVisible = false">{{ $t('common.cancel') }}</el-button>
  38 + <el-button type="primary" @click="importData" :loading="importing">
  39 + {{ $t('resourceStoreManage.import') }}
  40 + </el-button>
  41 + </div>
  42 + </el-dialog>
  43 +</template>
  44 +
  45 +<script>
  46 +import { importResourceStoreData,listStorehouses } from '@/api/resource/resourceStoreManageApi'
  47 +import { getCommunityId } from '@/api/community/communityApi'
  48 +
  49 +export default {
  50 + name: 'ImportResourceStore',
  51 + data() {
  52 + return {
  53 + dialogVisible: false,
  54 + formData: {
  55 + shId: '',
  56 + file: null,
  57 + communityId: getCommunityId()
  58 + },
  59 + storehouses: [],
  60 + fileName: '',
  61 + importing: false,
  62 + rules: {
  63 + shId: [
  64 + { required: true, message: this.$t('resourceStoreManage.storehouseRequired'), trigger: 'change' }
  65 + ],
  66 + file: [
  67 + { required: true, message: this.$t('resourceStoreManage.fileRequired'), trigger: 'change' }
  68 + ]
  69 + }
  70 + }
  71 + },
  72 + methods: {
  73 + open() {
  74 + this.dialogVisible = true
  75 + this.listStorehouses()
  76 + },
  77 +
  78 + async listStorehouses() {
  79 + try {
  80 + const params = {
  81 + page: 1,
  82 + row: 100,
  83 + communityId: getCommunityId()
  84 + }
  85 + const response = await listStorehouses(params)
  86 + this.storehouses = response.data || []
  87 + } catch (error) {
  88 + console.error('加载仓库列表失败:', error)
  89 + }
  90 + },
  91 +
  92 + handleFileChange(file) {
  93 + this.formData.file = file.raw
  94 + this.fileName = file.name
  95 + this.$refs.importForm.validateField('file')
  96 + },
  97 +
  98 + async importData() {
  99 + this.$refs.importForm.validate(async valid => {
  100 + if (!valid) return
  101 +
  102 + // 检查文件类型
  103 + const ext = this.fileName.split('.').pop().toLowerCase()
  104 + if (!['xls', 'xlsx'].includes(ext)) {
  105 + this.$message.error(this.$t('resourceStoreManage.invalidExcelFormat'))
  106 + return
  107 + }
  108 +
  109 + // 检查文件大小 (2MB)
  110 + if (this.formData.file.size > 2 * 1024 * 1024) {
  111 + this.$message.error(this.$t('resourceStoreManage.fileSizeLimit'))
  112 + return
  113 + }
  114 +
  115 + try {
  116 + this.importing = true
  117 +
  118 + const formData = new FormData()
  119 + formData.append('uploadFile', this.formData.file)
  120 + formData.append('shId', this.formData.shId)
  121 + formData.append('communityId', this.formData.communityId)
  122 +
  123 + await importResourceStoreData(formData)
  124 + this.$message.success(this.$t('resourceStoreManage.importSuccess'))
  125 + this.dialogVisible = false
  126 + this.$emit('success')
  127 + } catch (error) {
  128 + console.error('导入物品失败:', error)
  129 + this.$message.error(error.message || this.$t('resourceStoreManage.importFailed'))
  130 + } finally {
  131 + this.importing = false
  132 + }
  133 + })
  134 + },
  135 +
  136 + handleClosed() {
  137 + this.$refs.importForm.resetFields()
  138 + this.formData = {
  139 + shId: '',
  140 + file: null,
  141 + communityId: getCommunityId()
  142 + }
  143 + this.fileName = ''
  144 + }
  145 + }
  146 +}
  147 +</script>
  148 +
  149 +<style scoped>
  150 +.upload-demo {
  151 + display: flex;
  152 + align-items: center;
  153 +}
  154 +
  155 +.el-upload__tip {
  156 + margin-left: 10px;
  157 + color: #606266;
  158 +}
  159 +</style>
0 160 \ No newline at end of file
... ...
src/components/resource/resourceStoreTimes.vue 0 → 100644
  1 +<template>
  2 + <el-dialog
  3 + id="resourceStoreTimesModel"
  4 + :title="$t('resourceStoreTimes.title')"
  5 + :visible.sync="visible"
  6 + width="80%"
  7 + :before-close="handleClose"
  8 + >
  9 + <el-table :data="resourceStoreTimesInfo.timeses" border style="width: 100%">
  10 + <el-table-column prop="resCode" :label="$t('resourceStoreTimes.itemCode')" align="center" />
  11 + <el-table-column prop="createTime" :label="$t('resourceStoreTimes.inboundTime')" align="center" />
  12 + <el-table-column prop="price" :label="$t('resourceStoreTimes.unitPrice')" align="center" />
  13 + <el-table-column prop="stock" :label="$t('resourceStoreTimes.stock')" align="center" />
  14 + <el-table-column prop="totalPrice" :label="$t('resourceStoreTimes.totalPrice')" align="center" />
  15 + </el-table>
  16 + <div style="text-align: right; margin-top: 20px;">
  17 + <span>{{ $t('resourceStoreTimes.totalPrice') }}: {{ resourceStoreTimesInfo.totalPrice }}</span>
  18 + </div>
  19 + </el-dialog>
  20 +</template>
  21 +
  22 +<script>
  23 +import { listResourceStoreTimes } from '@/api/resource/resourceStoreManageApi'
  24 +
  25 +export default {
  26 + name: 'ResourceStoreTimes',
  27 + data() {
  28 + return {
  29 + visible: false,
  30 + resourceStoreTimesInfo: {
  31 + timeses: [],
  32 + resCode: '',
  33 + totalPrice: 0.0
  34 + }
  35 + }
  36 + },
  37 + methods: {
  38 + open(resourceStore) {
  39 + this.visible = true
  40 + this._loadAllResourceStoreTimes(1, 10, resourceStore.resCode, resourceStore.shId)
  41 + },
  42 + handleClose() {
  43 + this.visible = false
  44 + this.resourceStoreTimesInfo = {
  45 + timeses: [],
  46 + resCode: '',
  47 + totalPrice: 0.0
  48 + }
  49 + },
  50 + async _loadAllResourceStoreTimes(page, rows, resCode, shId) {
  51 + try {
  52 + const params = {
  53 + params: {
  54 + page: page,
  55 + row: rows,
  56 + resCode: resCode,
  57 + shId: shId
  58 + }
  59 + }
  60 + const { data, totalPrice } = await listResourceStoreTimes(params)
  61 + this.resourceStoreTimesInfo.timeses = data
  62 + this.resourceStoreTimesInfo.totalPrice = totalPrice.toFixed(2)
  63 + } catch (error) {
  64 + this.$message.error(this.$t('common.fetchError'))
  65 + }
  66 + }
  67 + }
  68 +}
  69 +</script>
  70 +
  71 +<style scoped>
  72 +</style>
0 73 \ No newline at end of file
... ...
src/components/resource/resourceStoreTypeTree.vue 0 → 100644
  1 +<template>
  2 + <div>
  3 +
  4 + <div class="bg-white margin-top-xs padding border-radius tree-div">
  5 + <el-tree :data="treeData" :props="defaultProps" default-expand-all @node-click="handleNodeClick"></el-tree>
  6 + </div>
  7 +
  8 + </div>
  9 +</template>
  10 +
  11 +<script>
  12 +import { listResourceStoreTypeTree } from '@/api/resource/resourceStoreManageApi'
  13 +
  14 +export default {
  15 + name: 'ResourceStoreTypeTree',
  16 + data() {
  17 + return {
  18 + treeData: [],
  19 + defaultProps: {
  20 + children: 'children',
  21 + label: 'name'
  22 + }
  23 + }
  24 + },
  25 + created() {
  26 + this._loadResourceStoreTypeTree()
  27 + },
  28 + methods: {
  29 + refreshTree() {
  30 + this._loadResourceStoreTypeTree()
  31 + },
  32 + async _loadResourceStoreTypeTree() {
  33 + try {
  34 + const { data } = await listResourceStoreTypeTree()
  35 + this.treeData = this._doTypeJsTreeData(data)
  36 + } catch (error) {
  37 + console.log('请求失败处理')
  38 + }
  39 + },
  40 + _doTypeJsTreeData(types) {
  41 + let mFloorTree = []
  42 + if (types && types.length > 0) {
  43 + types.forEach(pItem => {
  44 + let floorItem = {
  45 + id: 'f_' + pItem.parentRstId,
  46 + name: pItem.parentName,
  47 + children: []
  48 + }
  49 + if (pItem.subTypes) {
  50 + pItem.subTypes.forEach(subType => {
  51 + let menuItem = {
  52 + id: 'u_' + subType.rstId,
  53 + name: subType.name
  54 + }
  55 + floorItem.children.push(menuItem)
  56 + })
  57 + }
  58 + mFloorTree.push(floorItem)
  59 + })
  60 + }
  61 + return mFloorTree
  62 + },
  63 + handleNodeClick(data) {
  64 + if (data.id.startsWith('f_')) {
  65 + this.$emit('switchParent', { parentRstId: data.id.replace('f_', '') })
  66 + } else {
  67 + this.$emit('switchRst', { rstId: data.id.replace('u_', '') })
  68 + }
  69 + }
  70 + }
  71 +}
  72 +</script>
  73 +
  74 +<style scoped>
  75 +.tree-div {
  76 + background-color: white;
  77 + margin-top: 10px;
  78 + padding: 10px;
  79 + border-radius: 4px;
  80 +}
  81 +</style>
0 82 \ No newline at end of file
... ...
src/i18n/index.js
... ... @@ -179,6 +179,7 @@ import { messages as inspectionTaskDetailsMessages } from &#39;../views/inspection/i
179 179 import { messages as resourceAuditFlowMessages } from '../views/resource/resourceAuditFlowLang'
180 180 import { messages as storehouseManageMessages } from '../views/resource/storehouseManageLang'
181 181 import { messages as resourceStoreSpecificationManageMessages } from '../views/resource/resourceStoreSpecificationManageLang'
  182 +import { messages as resourceStoreManageMessages } from '../views/resource/resourceStoreManageLang'
182 183  
183 184 Vue.use(VueI18n)
184 185  
... ... @@ -362,6 +363,7 @@ const messages = {
362 363 ...resourceAuditFlowMessages.en,
363 364 ...storehouseManageMessages.en,
364 365 ...resourceStoreSpecificationManageMessages.en,
  366 + ...resourceStoreManageMessages.en,
365 367 },
366 368 zh: {
367 369 ...loginMessages.zh,
... ... @@ -541,6 +543,7 @@ const messages = {
541 543 ...resourceAuditFlowMessages.zh,
542 544 ...storehouseManageMessages.zh,
543 545 ...resourceStoreSpecificationManageMessages.zh,
  546 + ...resourceStoreManageMessages.zh,
544 547 }
545 548 }
546 549  
... ...
src/router/index.js
... ... @@ -877,15 +877,20 @@ const routes = [
877 877 component: () => import('@/views/resource/resourceAuditFlowList.vue')
878 878 },
879 879 {
880   - path:'/pages/property/storehouseManage',
881   - name:'/pages/property/storehouseManage',
  880 + path: '/pages/property/storehouseManage',
  881 + name: '/pages/property/storehouseManage',
882 882 component: () => import('@/views/resource/storehouseManageList.vue')
883   - },
884   - {
885   - path:'/pages/common/resourceStoreSpecificationManage',
886   - name:'/pages/common/resourceStoreSpecificationManage',
887   - component: () => import('@/views/resource/resourceStoreSpecificationManageList.vue')
888   - },
  883 + },
  884 + {
  885 + path: '/pages/common/resourceStoreSpecificationManage',
  886 + name: '/pages/common/resourceStoreSpecificationManage',
  887 + component: () => import('@/views/resource/resourceStoreSpecificationManageList.vue')
  888 + },
  889 + {
  890 + path: '/pages/common/resourceStoreManage',
  891 + name: '/pages/common/resourceStoreManage',
  892 + component: () => import('@/views/resource/resourceStoreManageList.vue')
  893 + },
889 894 // 其他子路由可以在这里添加
890 895 ]
891 896 },
... ...
src/views/resource/resourceStoreManageLang.js 0 → 100644
  1 +export const messages = {
  2 + en: {
  3 + resourceStoreManage: {
  4 + addFirstLevel: 'Add First Level',
  5 + addSecondLevel: 'Add Second Level',
  6 + edit: 'Edit',
  7 + delete: 'Delete',
  8 + queryCondition: 'Query Conditions',
  9 + selectStorehouse: 'Select Storehouse',
  10 + enterResourceName: 'Enter Resource Name',
  11 + enterResourceCode: 'Enter Resource Code',
  12 + selectSpec: 'Select Specification',
  13 + selectIsFixed: 'Select Fixed Resource',
  14 + query: 'Query',
  15 + reset: 'Reset',
  16 + resourceInfo: 'Resource Information',
  17 + add: 'Add',
  18 + directPurchase: 'Direct Purchase Inbound',
  19 + directOut: 'Direct Outbound',
  20 + import: 'Import',
  21 + export: 'Export',
  22 + back: 'Back',
  23 + resourceId: 'Resource ID',
  24 + resourceNameCode: 'Resource Name (Code)',
  25 + storeName: 'Storehouse Name',
  26 + resourceType: 'Resource Type',
  27 + resourceSpec: 'Specification',
  28 + referencePrice: 'Reference Price',
  29 + chargeStandard: 'Charge Standard',
  30 + stock: 'Stock',
  31 + minTotal: 'Min Total',
  32 + avgPrice: 'Avg Price',
  33 + totalPrice: 'Total Price',
  34 + operation: 'Operation',
  35 + subTotal: 'Sub Total',
  36 + grandTotal: 'Grand Total',
  37 + yuan: 'Yuan',
  38 + detail: 'Detail',
  39 + confirmOperation: 'Confirm Operation',
  40 + confirmDeleteResource: 'Confirm to delete resource?',
  41 + cancelDelete: 'Cancel',
  42 + confirmDelete: 'Confirm Delete',
  43 + addResource: 'Add Resource',
  44 + resourceName: 'Resource Name',
  45 + resourceCode: 'Resource Code',
  46 + secondCategory: 'Second Category',
  47 + unit: 'Unit',
  48 + fixedResource: 'Fixed Resource',
  49 + warningStock: 'Warning Stock',
  50 + minUnit: 'Min Unit',
  51 + minUnitTip: '[Example] 1 box of nails has 50 pieces, unit is box (1 box), min unit is piece (50 pieces).',
  52 + minUnitQty: 'Min Unit Quantity',
  53 + minCharge: 'Min Charge (Min Unit)',
  54 + maxCharge: 'Max Charge (Min Unit)',
  55 + initialStock: 'Initial Stock',
  56 + remark: 'Remark',
  57 + description: 'Description',
  58 + uploadImage: 'Upload Image',
  59 + selectResourceType: 'Select Resource Type',
  60 + selectSecondCategory: 'Select Second Category',
  61 + selectUnit: 'Select Unit',
  62 + enterReferencePrice: 'Enter Reference Price',
  63 + enterWarningStock: 'Enter Warning Stock',
  64 + selectMinUnit: 'Select Min Unit',
  65 + enterMinUnitQty: 'Enter Min Unit Quantity',
  66 + enterMinCharge: 'Enter Min Charge',
  67 + enterMaxCharge: 'Enter Max Charge',
  68 + enterInitialStock: 'Enter Initial Stock',
  69 + enterRemark: 'Enter Remark',
  70 + enterDescription: 'Enter Description',
  71 + addSuccess: 'Add Success',
  72 + resourceNameRequired: 'Resource name is required',
  73 + resourceNameLength: 'Resource name length 2-100 characters',
  74 + resourceCodeRequired: 'Resource code is required',
  75 + resourceCodeMaxLength: 'Resource code max length 50 characters',
  76 + resourceTypeRequired: 'Resource type is required',
  77 + secondCategoryRequired: 'Second category is required',
  78 + unitRequired: 'Unit is required',
  79 + isFixedRequired: 'Fixed resource is required',
  80 + storehouseRequired: 'Storehouse is required',
  81 + referencePriceRequired: 'Reference price is required',
  82 + priceFormatError: 'Price format error',
  83 + warningStockRequired: 'Warning stock is required',
  84 + warningStockMin: 'Warning stock min is 0',
  85 + minUnitRequired: 'Min unit is required',
  86 + minUnitQtyRequired: 'Min unit quantity is required',
  87 + minChargeRequired: 'Min charge is required',
  88 + maxChargeRequired: 'Max charge is required',
  89 + chargeFormatError: 'Charge format error',
  90 + initialStockRequired: 'Initial stock is required',
  91 + maxChargeError: 'Max charge cannot be less than min charge',
  92 + editResource: 'Edit Resource',
  93 + updateSuccess: 'Update Success',
  94 + confirmDeleteResourceType: 'Confirm to delete resource type?',
  95 + importResource: 'Import Resource',
  96 + browse: 'Browse',
  97 + selectDataFile: 'Select data file',
  98 + downloadTemplate: 'Download Template',
  99 + downloadTemplateTip1: 'Please download',
  100 + resourceTemplate: 'Resource Template',
  101 + downloadTemplateTip2: 'prepare data, then upload to import',
  102 + importSuccess: 'Import Success',
  103 + fileRequired: 'File is required',
  104 + invalidExcelFormat: 'Invalid Excel format',
  105 + fileSizeLimit: 'File size cannot exceed 2MB',
  106 + addFirstLevelType: 'Add First Level Type',
  107 + addSecondLevelType: 'Add Second Level Type',
  108 + typeName: 'Type Name',
  109 + enterTypeName: 'Enter type name',
  110 + enterTypeDescription: 'Enter type description',
  111 + typeNameRequired: 'Type name is required',
  112 + addTypeSuccess: 'Add type success',
  113 + editResourceType: 'Edit Resource Type',
  114 + updateTypeSuccess: 'Update type success',
  115 + deleteTypeSuccess: 'Delete type success',
  116 + inboundTime: 'Inbound Time',
  117 + unitPrice: 'Unit Price',
  118 + fetchTotalPriceError: 'Failed to get total price details'
  119 + }
  120 + },
  121 + zh: {
  122 + resourceStoreManage: {
  123 + addFirstLevel: '添加一级',
  124 + addSecondLevel: '添加二级',
  125 + edit: '修改',
  126 + delete: '删除',
  127 + queryCondition: '查询条件',
  128 + selectStorehouse: '请选择仓库',
  129 + enterResourceName: '请输入物品名称',
  130 + enterResourceCode: '请输入物品编码',
  131 + selectSpec: '请选择物品规格',
  132 + selectIsFixed: '请选择物品是否固定',
  133 + query: '查询',
  134 + reset: '重置',
  135 + resourceInfo: '物品信息',
  136 + add: '添加',
  137 + directPurchase: '直接采购入库',
  138 + directOut: '直接出库',
  139 + import: '导入',
  140 + export: '导出',
  141 + back: '返回',
  142 + resourceId: '物品ID',
  143 + resourceNameCode: '物品名称(编号)',
  144 + storeName: '仓库名称',
  145 + resourceType: '物品类型',
  146 + resourceSpec: '物品规格',
  147 + fixedResource: '固定物品',
  148 + referencePrice: '参考价格',
  149 + chargeStandard: '收费标准',
  150 + stock: '物品库存',
  151 + minUnit: '最小计量',
  152 + minTotal: '最小计量总数',
  153 + avgPrice: '物品均价',
  154 + totalPrice: '物品总价',
  155 + operation: '操作',
  156 + subTotal: '小计',
  157 + grandTotal: '大计',
  158 + yuan: '元',
  159 + detail: '详情',
  160 + confirmOperation: '请确认您的操作',
  161 + confirmDeleteResource: '确定删除物品管理?',
  162 + cancelDelete: '点错了',
  163 + confirmDelete: '确认删除',
  164 + addResource: '添加物品',
  165 + resourceName: '物品名称',
  166 + resourceCode: '物品编码',
  167 + secondCategory: '二级分类',
  168 + unit: '物品单位',
  169 + warningStock: '警告库存',
  170 + minUnitTip: '【例】1盒钉子50个,物品单位为盒(1盒),最小计量单位为个(50个)',
  171 + minUnitQty: '最小计量数量',
  172 + minCharge: '最低收费标准(最小计量单位)',
  173 + maxCharge: '最高收费标准(最小计量单位)',
  174 + initialStock: '初始库存',
  175 + remark: '备注',
  176 + description: '描述',
  177 + uploadImage: '上传图片',
  178 + selectResourceType: '请选择物品类型',
  179 + selectSecondCategory: '请选择二级分类',
  180 + selectUnit: '请选择物品单位',
  181 + enterReferencePrice: '请输入物品采购参考价格',
  182 + enterWarningStock: '请输入警告库存',
  183 + selectMinUnit: '请选择物品最小计量单位',
  184 + enterMinUnitQty: '请输入最小计量单位数量',
  185 + enterMinCharge: '请输入物品最小计量单位,最低收费标准',
  186 + enterMaxCharge: '请输入物品最小计量单位,最高收费标准',
  187 + enterInitialStock: '请输入出入库存',
  188 + enterRemark: '请填写备注',
  189 + enterDescription: '请填写描述',
  190 + addSuccess: '添加成功',
  191 + resourceNameRequired: '物品名称不能为空',
  192 + resourceNameLength: '物品名称长度为2至100',
  193 + resourceCodeRequired: '物品编码不能为空',
  194 + resourceCodeMaxLength: '物品编码不能超过50位',
  195 + resourceTypeRequired: '物品类型不能为空',
  196 + secondCategoryRequired: '二级分类不能为空',
  197 + unitRequired: '单位不能为空',
  198 + isFixedRequired: '是否是固定物品不能为空',
  199 + storehouseRequired: '仓库不能为空',
  200 + referencePriceRequired: '物品价格不能为空',
  201 + priceFormatError: '物品价格格式错误',
  202 + warningStockRequired: '警告库存不能为空',
  203 + warningStockMin: '警告库存最小为零',
  204 + minUnitRequired: '最小计量单位不能为空',
  205 + minUnitQtyRequired: '最小计量单位数量不能为空',
  206 + minChargeRequired: '最低收费标准不能为空',
  207 + maxChargeRequired: '最高收费标准不能为空',
  208 + chargeFormatError: '收费标准格式错误',
  209 + initialStockRequired: '出入库存不能为空',
  210 + maxChargeError: '最高收费标准不能小于最低收费标准',
  211 + editResource: '修改物品',
  212 + updateSuccess: '修改成功',
  213 + confirmDeleteResourceType: '确定删除物品类型?',
  214 + importResource: '物品导入',
  215 + browse: '浏览',
  216 + selectDataFile: '请选择数据文件',
  217 + downloadTemplate: '下载模板',
  218 + downloadTemplateTip1: '请先下载',
  219 + resourceTemplate: '物品模板',
  220 + downloadTemplateTip2: '准备数据后,上传导入',
  221 + importSuccess: '导入成功',
  222 + fileRequired: '文件不能为空',
  223 + invalidExcelFormat: '不是有效的Excel格式',
  224 + fileSizeLimit: 'Excel文件大小不能超过2M',
  225 + addFirstLevelType: '添加一级类型',
  226 + addSecondLevelType: '添加二级类型',
  227 + typeName: '类型名称',
  228 + enterTypeName: '请填写物品类型名称',
  229 + enterTypeDescription: '请填写物品类型描述',
  230 + typeNameRequired: '类型名称不能为空',
  231 + addTypeSuccess: '添加类型成功',
  232 + editResourceType: '修改物品类型',
  233 + updateTypeSuccess: '修改类型成功',
  234 + deleteTypeSuccess: '删除类型成功',
  235 + inboundTime: '入库时间',
  236 + unitPrice: '单价',
  237 + fetchTotalPriceError: '获取物品总价详情失败'
  238 + }
  239 + }
  240 +}
0 241 \ No newline at end of file
... ...
src/views/resource/resourceStoreManageList.vue 0 → 100644
  1 +<template>
  2 + <div class="animated fadeInRight ecommerce">
  3 + <el-row :gutter="20">
  4 + <el-col :span="5" class="tree-container">
  5 + <div class="tree-header">
  6 + <el-button type="primary" size="small" @click="openAddResourceStoreTypeModal(1)">
  7 + {{ $t('resourceStoreManage.addFirstLevel') }}
  8 + </el-button>
  9 + <el-button type="primary" size="small" @click="openAddResourceStoreTypeModal(2)">
  10 + {{ $t('resourceStoreManage.addSecondLevel') }}
  11 + </el-button>
  12 + <el-button type="primary" size="small" @click="openEditResourceStoreTypeModel">
  13 + {{ $t('resourceStoreManage.edit') }}
  14 + </el-button>
  15 + <el-button type="primary" size="small" @click="openDeleteResourceStoreTypeModel">
  16 + {{ $t('resourceStoreManage.delete') }}
  17 + </el-button>
  18 + </div>
  19 + <resource-store-type-tree ref="resourceStoreTypeTree" @switchParent="switchParent" @switchRst="switchRst" />
  20 + </el-col>
  21 + <el-col :span="19">
  22 + <el-card class="margin-top-xs">
  23 + <div slot="header" class="text-left">
  24 + <span>{{ $t('resourceStoreManage.queryCondition') }}</span>
  25 + </div>
  26 + <el-row :gutter="20">
  27 + <el-col :span="4">
  28 + <el-select v-model="resourceStoreManageInfo.conditions.shId" style="width:100%">
  29 + <el-option :label="$t('resourceStoreManage.selectStorehouse')" value=""></el-option>
  30 + <el-option v-for="(item, index) in resourceStoreManageInfo.storehouses" :key="index" :label="item.shName"
  31 + :value="item.shId"></el-option>
  32 + </el-select>
  33 + </el-col>
  34 + <el-col :span="4">
  35 + <el-input :placeholder="$t('resourceStoreManage.enterResourceName')"
  36 + v-model.trim="resourceStoreManageInfo.conditions.resName"></el-input>
  37 + </el-col>
  38 + <el-col :span="4">
  39 + <el-input :placeholder="$t('resourceStoreManage.enterResourceCode')"
  40 + v-model.trim="resourceStoreManageInfo.conditions.resCode"></el-input>
  41 + </el-col>
  42 + <el-col :span="4">
  43 + <el-select v-model="resourceStoreManageInfo.conditions.rssId" style="width:100%">
  44 + <el-option :label="$t('resourceStoreManage.selectSpec')" value=""></el-option>
  45 + <el-option v-for="(item, index) in resourceStoreManageInfo.resourceStoreSpecifications" :key="index"
  46 + :label="item.specName" :value="item.rssId"></el-option>
  47 + </el-select>
  48 + </el-col>
  49 + <el-col :span="4" >
  50 + <el-select v-model="resourceStoreManageInfo.conditions.isFixed" style="width:100%">
  51 + <el-option :label="$t('resourceStoreManage.selectIsFixed')" value=""></el-option>
  52 + <el-option v-for="(item, index) in resourceStoreManageInfo.isFixeds" :key="index" :label="item.name"
  53 + :value="item.statusCd"></el-option>
  54 + </el-select>
  55 + </el-col>
  56 + <el-col :span="4">
  57 + <el-button type="primary" size="small" @click="queryResourceStoreMethod">
  58 + <i class="el-icon-search"></i>
  59 + {{ $t('resourceStoreManage.query') }}
  60 + </el-button>
  61 + <el-button type="primary" size="small" @click="resetResourceStoreMethod">
  62 + <i class="el-icon-refresh"></i>
  63 + {{ $t('resourceStoreManage.reset') }}
  64 + </el-button>
  65 + </el-col>
  66 + </el-row>
  67 + </el-card>
  68 +
  69 + <el-card class="margin-top-xs">
  70 + <div slot="header" class="card-header">
  71 + <span>{{ $t('resourceStoreManage.resourceInfo') }}</span>
  72 + <div>
  73 + <el-button type="primary" size="small" @click="openAddResourceStoreModal"
  74 + v-if="hasPrivilege('502022081709270004')">
  75 + <i class="el-icon-plus"></i>
  76 + {{ $t('resourceStoreManage.add') }}
  77 + </el-button>
  78 + <el-button type="primary" size="small" @click="jump2InPage" v-if="hasPrivilege('502021042137960001')">
  79 + <i class="el-icon-plus"></i>
  80 + {{ $t('resourceStoreManage.directPurchase') }}
  81 + </el-button>
  82 + <el-button type="primary" size="small" @click="jump2OutPage" v-if="hasPrivilege('502021042137960001')">
  83 + <i class="el-icon-plus"></i>
  84 + {{ $t('resourceStoreManage.directOut') }}
  85 + </el-button>
  86 + <el-button type="primary" size="small" @click="importResourceStoreModal"
  87 + v-if="hasPrivilege('502022081750470005')">
  88 + <i class="el-icon-upload"></i>
  89 + {{ $t('resourceStoreManage.import') }}
  90 + </el-button>
  91 + <el-button type="primary" size="small" @click="exportExcel">
  92 + <i class="el-icon-download"></i>
  93 + {{ $t('resourceStoreManage.export') }}
  94 + </el-button>
  95 + <el-button type="primary" size="small" @click="goBack"
  96 + v-if="resourceStoreManageInfo.conditions.flag == '1'">
  97 + <i class="el-icon-close"></i>
  98 + {{ $t('resourceStoreManage.back') }}
  99 + </el-button>
  100 + </div>
  101 + </div>
  102 + <el-table :data="resourceStoreManageInfo.resourceStores" border style="width:100%">
  103 + <el-table-column prop="resId" :label="$t('resourceStoreManage.resourceId')" align="center"></el-table-column>
  104 + <el-table-column :label="$t('resourceStoreManage.resourceNameCode')" align="center">
  105 + <template slot-scope="scope">
  106 + {{ scope.row.resName }}({{ scope.row.resCode }})
  107 + </template>
  108 + </el-table-column>
  109 + <el-table-column prop="shName" :label="$t('resourceStoreManage.storeName')" align="center"></el-table-column>
  110 + <el-table-column :label="$t('resourceStoreManage.resourceType')" align="center">
  111 + <template slot-scope="scope">
  112 + {{ scope.row.parentRstName }}
  113 + {{ scope.row.rstName ? ' > ' + scope.row.rstName : '' }}
  114 + </template>
  115 + </el-table-column>
  116 + <el-table-column :label="$t('resourceStoreManage.resourceSpec')" align="center">
  117 + <template slot-scope="scope">
  118 + {{ scope.row.rssName ? scope.row.rssName : '-' }}
  119 + </template>
  120 + </el-table-column>
  121 + <el-table-column prop="isFixedName" :label="$t('resourceStoreManage.fixedResource')"
  122 + align="center"></el-table-column>
  123 + <el-table-column :label="$t('resourceStoreManage.referencePrice')" align="center">
  124 + <template slot-scope="scope">
  125 + {{ '¥' + scope.row.price }}
  126 + </template>
  127 + </el-table-column>
  128 + <el-table-column :label="$t('resourceStoreManage.chargeStandard')" align="center">
  129 + <template slot-scope="scope">
  130 + {{ scope.row.outHighPrice == scope.row.outLowPrice
  131 + ? '¥' + scope.row.outLowPrice
  132 + : '¥' + scope.row.outLowPrice + '-¥' + scope.row.outHighPrice }}
  133 + </template>
  134 + </el-table-column>
  135 + <el-table-column :label="$t('resourceStoreManage.stock')" align="center">
  136 + <template slot-scope="scope">
  137 + {{ scope.row.stock }}{{ scope.row.unitCodeName }}
  138 + </template>
  139 + </el-table-column>
  140 + <el-table-column :label="$t('resourceStoreManage.minUnit')" align="center">
  141 + <template slot-scope="scope">
  142 + 1{{ scope.row.unitCodeName }}={{ scope.row.miniUnitStock }}{{ scope.row.miniUnitCodeName }}
  143 + </template>
  144 + </el-table-column>
  145 + <el-table-column :label="$t('resourceStoreManage.minTotal')" align="center">
  146 + <template slot-scope="scope">
  147 + {{ scope.row.miniStock }}{{ scope.row.miniUnitCodeName }}
  148 + </template>
  149 + </el-table-column>
  150 + <el-table-column :label="$t('resourceStoreManage.avgPrice')" align="center">
  151 + <template slot-scope="scope">
  152 + {{ scope.row.averagePrice ? '¥' + scope.row.averagePrice : '¥0' }}
  153 + </template>
  154 + </el-table-column>
  155 + <el-table-column :label="$t('resourceStoreManage.totalPrice')" align="center">
  156 + <template slot-scope="scope">
  157 + <el-link type="primary" @click="queryTotalPrice(scope.row)">{{ $t('resourceStoreManage.query')
  158 + }}</el-link>
  159 + </template>
  160 + </el-table-column>
  161 + <el-table-column :label="$t('resourceStoreManage.operation')" align="center" width="200">
  162 + <template slot-scope="scope">
  163 + <el-button-group>
  164 + <el-button size="mini" type="primary" v-if="hasPrivilege('502022081701700001')"
  165 + @click="openEditResourceStoreModel(scope.row)">
  166 + {{ $t('resourceStoreManage.edit') }}
  167 + </el-button>
  168 + <el-button size="mini" type="danger" v-if="hasPrivilege('502022081741410002')"
  169 + @click="openDeleteResourceStoreModel(scope.row)">
  170 + {{ $t('resourceStoreManage.delete') }}
  171 + </el-button>
  172 + <el-button size="mini" type="info" @click="toResourceStoreDetail(scope.row)">
  173 + {{ $t('resourceStoreManage.detail') }}
  174 + </el-button>
  175 + </el-button-group>
  176 + </template>
  177 + </el-table-column>
  178 + </el-table>
  179 +
  180 + <el-row class="margin-top">
  181 + <el-col :span="12" class="text-left">
  182 + <div>
  183 + <b>{{ $t('resourceStoreManage.subTotal') }}</b>
  184 + <span class="margin-left">
  185 + {{ $t('resourceStoreManage.totalPrice') }}:{{ resourceStoreManageInfo.subTotalPrice }}
  186 + {{ $t('resourceStoreManage.yuan') }}
  187 + </span>
  188 + </div>
  189 + <div class="margin-top-xs">
  190 + <b>{{ $t('resourceStoreManage.grandTotal') }}</b>
  191 + <span class="margin-left">
  192 + {{ $t('resourceStoreManage.totalPrice') }}:{{ resourceStoreManageInfo.highTotalPrice }}
  193 + {{ $t('resourceStoreManage.yuan') }}
  194 + </span>
  195 + </div>
  196 + </el-col>
  197 + <el-col :span="12" class="text-right">
  198 + <el-pagination :current-page.sync="pagination.current" :page-sizes="[10, 20, 30, 50]"
  199 + :page-size="pagination.size" :total="pagination.total" layout="total, sizes, prev, pager, next, jumper"
  200 + @size-change="handleSizeChange" @current-change="handlePageChange"></el-pagination>
  201 + </el-col>
  202 + </el-row>
  203 + </el-card>
  204 + </el-col>
  205 + </el-row>
  206 +
  207 + <!-- 子组件 -->
  208 + <add-resource-store ref="addResourceStore" @success="handleResourceStoreSuccess" />
  209 + <edit-resource-store ref="editResourceStore" @success="handleResourceStoreSuccess" />
  210 + <delete-resource-store ref="deleteResourceStore" @success="handleResourceStoreSuccess" />
  211 + <resource-store-times ref="resourceStoreTimes" />
  212 + <import-resource-store ref="importResourceStore" @success="handleResourceStoreSuccess" />
  213 + <add-resource-store-type ref="addResourceStoreType" @success="handleResourceStoreTypeSuccess" />
  214 + <edit-resource-store-type ref="editResourceStoreType" @success="handleResourceStoreTypeSuccess" />
  215 + <delete-resource-store-type ref="deleteResourceStoreType" @success="handleResourceStoreTypeSuccess" />
  216 + </div>
  217 +</template>
  218 +
  219 +<script>
  220 +import { getDict, getCommunityId } from '@/api/community/communityApi'
  221 +import { listResourceStores, exportResourceStoreData, listResourceStoreSpecifications, listStorehouses, listResourceStoreTypes } from '@/api/resource/resourceStoreManageApi'
  222 +//import { } from '@/api/resource/resourceStoreTypeApi'
  223 +import ResourceStoreTypeTree from '@/components/resource/resourceStoreTypeTree'
  224 +import AddResourceStore from '@/components/resource/addResourceStore'
  225 +import EditResourceStore from '@/components/resource/editResourceStore'
  226 +import DeleteResourceStore from '@/components/resource/deleteResourceStore'
  227 +import ResourceStoreTimes from '@/components/resource/resourceStoreTimes'
  228 +import ImportResourceStore from '@/components/resource/importResourceStore'
  229 +import AddResourceStoreType from '@/components/resource/addResourceStoreType'
  230 +import EditResourceStoreType from '@/components/resource/editResourceStoreType'
  231 +import DeleteResourceStoreType from '@/components/resource/deleteResourceStoreType'
  232 +
  233 +export default {
  234 + name: 'ResourceStoreManageList',
  235 + components: {
  236 + ResourceStoreTypeTree,
  237 + AddResourceStore,
  238 + EditResourceStore,
  239 + DeleteResourceStore,
  240 + ResourceStoreTimes,
  241 + ImportResourceStore,
  242 + AddResourceStoreType,
  243 + EditResourceStoreType,
  244 + DeleteResourceStoreType
  245 + },
  246 + data() {
  247 + return {
  248 + resourceStoreManageInfo: {
  249 + resourceStores: [],
  250 + total: 0,
  251 + records: 1,
  252 + subTotalPrice: 0.0,
  253 + highTotalPrice: 0.0,
  254 + isFixeds: [],
  255 + conditions: {
  256 + resId: '',
  257 + resName: '',
  258 + resCode: '',
  259 + shId: '',
  260 + parentRstId: '',
  261 + rstId: '',
  262 + rssId: '',
  263 + isFixed: '',
  264 + flag: '',
  265 + userId: '',
  266 + communityId: '',
  267 + page: 1,
  268 + row: 10
  269 + },
  270 + curType: {},
  271 + storehouses: [],
  272 + resourceStoreSpecifications: []
  273 + },
  274 + pagination: {
  275 + current: 1,
  276 + size: 10,
  277 + total: 0
  278 + }
  279 + }
  280 + },
  281 + created() {
  282 + this.communityId = getCommunityId()
  283 + this.resourceStoreManageInfo.conditions.communityId = this.communityId
  284 + this.userInfo = JSON.parse(localStorage.getItem('userInfo'))
  285 +
  286 + const flag = this.$route.query.flag
  287 + if (flag) {
  288 + this.resourceStoreManageInfo.conditions.flag = flag
  289 + }
  290 +
  291 + this.initData()
  292 + },
  293 + methods: {
  294 + async initData() {
  295 + await this.loadDictData()
  296 + await this.listResourceStores()
  297 + await this.listStorehouses()
  298 + await this.listResourceStoreSpecifications()
  299 + },
  300 +
  301 + async loadDictData() {
  302 + try {
  303 + const data = await getDict('resource_store', 'is_fixed')
  304 + this.resourceStoreManageInfo.isFixeds = data
  305 + } catch (error) {
  306 + console.error('获取字典数据失败:', error)
  307 + }
  308 + },
  309 +
  310 + async listResourceStores() {
  311 + try {
  312 + this.resourceStoreManageInfo.conditions.page = this.pagination.current
  313 + this.resourceStoreManageInfo.conditions.row = this.pagination.size
  314 +
  315 + const response = await listResourceStores(this.resourceStoreManageInfo.conditions)
  316 + const data = response
  317 +
  318 + this.resourceStoreManageInfo.resourceStores = data.resourceStores || []
  319 + this.resourceStoreManageInfo.subTotalPrice = data.subTotal || 0
  320 + this.resourceStoreManageInfo.highTotalPrice = data.totalPrice || 0
  321 + this.pagination.total = data.total || 0
  322 + } catch (error) {
  323 + console.error('获取物品列表失败:', error)
  324 + }
  325 + },
  326 +
  327 + async listStorehouses() {
  328 + try {
  329 + const params = {
  330 + communityId: this.communityId,
  331 + page: 1,
  332 + row: 100
  333 + }
  334 + const response = await listStorehouses(params)
  335 + this.resourceStoreManageInfo.storehouses = response.data || []
  336 + } catch (error) {
  337 + console.error('获取仓库列表失败:', error)
  338 + }
  339 + },
  340 +
  341 + async listResourceStoreSpecifications() {
  342 + try {
  343 + const params = {
  344 + communityId: this.communityId,
  345 + page: 1,
  346 + row: 100
  347 + }
  348 + const response = await listResourceStoreSpecifications(params)
  349 + this.resourceStoreManageInfo.resourceStoreSpecifications = response.data || []
  350 + } catch (error) {
  351 + console.error('获取物品规格列表失败:', error)
  352 + }
  353 + },
  354 +
  355 + handlePageChange(currentPage) {
  356 + this.pagination.current = currentPage
  357 + this.listResourceStores()
  358 + },
  359 +
  360 + handleSizeChange(size) {
  361 + this.pagination.size = size
  362 + this.listResourceStores()
  363 + },
  364 +
  365 + queryResourceStoreMethod() {
  366 + this.pagination.current = 1
  367 + this.listResourceStores()
  368 + },
  369 +
  370 + resetResourceStoreMethod() {
  371 + this.resourceStoreManageInfo.conditions = {
  372 + ...this.resourceStoreManageInfo.conditions,
  373 + resId: '',
  374 + resName: '',
  375 + resCode: '',
  376 + shId: '',
  377 + rstId: '',
  378 + parentRstId: '',
  379 + rssId: '',
  380 + isFixed: ''
  381 + }
  382 + this.pagination.current = 1
  383 + this.listResourceStores()
  384 + },
  385 +
  386 + openAddResourceStoreModal() {
  387 + this.$refs.addResourceStore.open()
  388 + },
  389 +
  390 + openEditResourceStoreModel(row) {
  391 + this.$refs.editResourceStore.open(row)
  392 + },
  393 +
  394 + openDeleteResourceStoreModel(row) {
  395 + this.$refs.deleteResourceStore.open(row)
  396 + },
  397 +
  398 + openAddResourceStoreTypeModal(level) {
  399 + let _curType = this.resourceStoreManageInfo.curType;
  400 + if (level == 1) {
  401 + this.$refs.addResourceStoreType.open()
  402 + } else {
  403 + this.$refs.addResourceStoreType.open(_curType.rstId)
  404 + }
  405 + },
  406 +
  407 + openDeleteResourceStoreTypeModel() {
  408 + let _curType = this.resourceStoreManageInfo.curType;
  409 + if (!_curType.rstId) {
  410 +
  411 + return;
  412 + }
  413 + this.$refs.deleteResourceStoreType.open(_curType)
  414 + },
  415 +
  416 + openEditResourceStoreTypeModel() {
  417 + let _curType = this.resourceStoreManageInfo.curType;
  418 + if (!_curType.rstId) {
  419 + this.$message.error(this.$t('resourceStoreManage.selectType'))
  420 + return;
  421 + }
  422 + this.$refs.editResourceStoreType.open(_curType)
  423 + },
  424 +
  425 + importResourceStoreModal() {
  426 + this.$refs.importResourceStore.open()
  427 + },
  428 +
  429 + queryTotalPrice(row) {
  430 + this.$refs.resourceStoreTimes.open(row)
  431 + },
  432 +
  433 + switchParent(param) {
  434 + console.log(param)
  435 + this.resourceStoreManageInfo.conditions.parentRstId = param.parentRstId
  436 + this.resourceStoreManageInfo.conditions.rstId = ''
  437 + this.listResourceStoreType(param.parentRstId)
  438 + this.listResourceStores()
  439 + },
  440 +
  441 + switchRst(param) {
  442 + this.resourceStoreManageInfo.conditions.parentRstId = ''
  443 + this.resourceStoreManageInfo.conditions.rstId = param.rstId
  444 + this.listResourceStoreType(param.rstId)
  445 + this.listResourceStores()
  446 + },
  447 + async listResourceStoreType(rstId) {
  448 + const { data } = await listResourceStoreTypes({ page: 1, row: 1, rstId: rstId, communityId: this.getCommunityId() })
  449 + this.resourceStoreManageInfo.curType = data[0]
  450 + },
  451 +
  452 + handleResourceStoreSuccess() {
  453 + this.listResourceStores()
  454 + },
  455 +
  456 + handleResourceStoreTypeSuccess() {
  457 + this.$refs.resourceStoreTypeTree.refreshTree()
  458 + },
  459 +
  460 + async exportExcel() {
  461 + try {
  462 + this.resourceStoreManageInfo.conditions.pagePath = 'resourceStoreManage'
  463 + await exportResourceStoreData(this.resourceStoreManageInfo.conditions)
  464 + this.$message.success(this.$t('resourceStoreManage.exportSuccess'))
  465 + } catch (error) {
  466 + console.error('导出失败:', error)
  467 + this.$message.error(this.$t('resourceStoreManage.exportFailed'))
  468 + }
  469 + },
  470 +
  471 + jump2InPage() {
  472 + this.$router.push({
  473 + path: '/resource/addPurchaseApply',
  474 + query: {
  475 + resOrderType: '10000',
  476 + purchaseSwitch: 'OFF'
  477 + }
  478 + })
  479 + },
  480 +
  481 + jump2OutPage() {
  482 + this.$router.push({
  483 + path: '/resource/addItemOut',
  484 + query: {
  485 + resOrderType: '20000',
  486 + from: 'resourceStore'
  487 + }
  488 + })
  489 + },
  490 +
  491 + toResourceStoreDetail(resource) {
  492 + window.open(`/#/resource/resourceDetail?resId=${resource.resId}`)
  493 + },
  494 +
  495 + goBack() {
  496 + this.$router.go(-1)
  497 + },
  498 + }
  499 +}
  500 +</script>
  501 +
  502 +<style scoped>
  503 +.animated {
  504 + padding: 15px;
  505 +}
  506 +
  507 +.tree-container {
  508 + padding-right: 0;
  509 + height: 85vh;
  510 + overflow-y: auto;
  511 + border-right: 1px solid #ebeef5;
  512 +}
  513 +
  514 +.tree-header {
  515 + margin-bottom: 15px;
  516 +}
  517 +
  518 +.tree-header .el-button {
  519 + margin-bottom: 5px;
  520 +}
  521 +
  522 +.card-header {
  523 + display: flex;
  524 + justify-content: space-between;
  525 + align-items: center;
  526 +}
  527 +
  528 +.margin-top {
  529 + margin-top: 20px;
  530 +}
  531 +
  532 +.margin-top-xs {
  533 + margin-top: 10px;
  534 +}
  535 +
  536 +.margin-left {
  537 + margin-left: 10px;
  538 +}
  539 +
  540 +.text-left {
  541 + text-align: left;
  542 +}
  543 +
  544 +.text-right {
  545 + text-align: right;
  546 +}
  547 +</style>
0 548 \ No newline at end of file
... ...