SKUList.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370
  1. <template>
  2. <div>
  3. <en-table-layout :tableData="tableData.records" :loading="loading">
  4. <template #toolbar>
  5. <div class="inner-toolbar w-11/12 flex justify-between">
  6. <div class="toolbar-btns">
  7. <el-button size="small" v-if="checkPermission(['warehouse:add'])&& store.state.user.user.founder!==1" type="primary" @click="handleAddWarehouse">新增</el-button>
  8. </div>
  9. <div class="toolbar-search">
  10. <en-table-search @search="searchEvent" placeholder="请输入关键字搜索" />
  11. </div>
  12. </div>
  13. </template>
  14. <template #table-columns>
  15. <el-table-column prop="name" label="产品名称" />
  16. <el-table-column prop="brand" label="品牌" />
  17. <el-table-column prop="bar_code" label="条码" />
  18. <el-table-column prop="sku" label="sku" />
  19. <el-table-column prop="weight" label="重量" />
  20. <el-table-column prop="unit" label="单位" />
  21. <el-table-column prop="image" label="产品图片">
  22. <template #default="scope">
  23. <img :src="scope.row.image" alt="" />
  24. </template>
  25. </el-table-column>
  26. <el-table-column label="操作">
  27. <template #default="scope">
  28. <el-button size="small" v-if="checkPermission(['warehouse:update'])" @click="handleView(scope.row)">查看</el-button>
  29. <el-button size="small" v-if="checkPermission(['warehouse:update'])&& store.state.user.user.founder!==1" @click="handleEditWarehouse(scope.$index, scope.row)">编辑</el-button>
  30. <el-button type="success" size="small" v-if="checkPermission(['removeAreaType:delete'])&& store.state.user.user.founder!==1" @click="handleDelGoods(scope.row)">删除</el-button>
  31. <!--<el-button size="mini" v-if="checkPermission(['warehouse:update'])" @click="handleRenew(scope.$index, scope.row)">续费</el-button> -->
  32. </template>
  33. </el-table-column>
  34. </template>
  35. <template #pagination>
  36. <el-pagination
  37. v-if="tableData.records && tableData.records.length"
  38. @size-change="handlePageSizeChange"
  39. @current-change="handlePageCurrentChange"
  40. :current-page="tableData.page_no"
  41. :page-sizes="[10, 20, 50, 100]"
  42. :page-size="tableData.page_size"
  43. layout="total, sizes, prev, pager, next, jumper"
  44. :total="tableData.data_total"
  45. >
  46. </el-pagination>
  47. </template>
  48. </en-table-layout>
  49. <el-dialog
  50. :title="skuForm.id ? '编辑商品' : '新建商品'"
  51. v-model="dialogVisible"
  52. @open="handleDialogOpen"
  53. :modal-append-to-body="false"
  54. :close-on-click-modal="false"
  55. :close-on-press-escape="false"
  56. >
  57. <el-form :model="skuForm" :rules="stockRules" ref="skuFormRef" label-width="140px">
  58. <el-row>
  59. <!--<el-col :span="10" v-if="!skuForm.id">
  60. <el-form-item label="套餐:" prop="company_package_id">
  61. <el-select v-model="skuForm.company_package_id" clearable placeholder="请选择套餐">
  62. <el-option v-for="item in packageList" :key="item.id" :label="item.name" :value="item.id" />
  63. </el-select>
  64. </el-form-item>
  65. </el-col> -->
  66. <el-col :span="10">
  67. <el-form-item label="产品名称:" prop="name">
  68. <el-input v-model="skuForm.name" :minlength="2" :maxlength="20" :disabled="disabled" clearable placeholder="请输入产品名称"></el-input>
  69. </el-form-item>
  70. </el-col>
  71. <el-col :span="10">
  72. <el-form-item label="品牌:" prop="brand">
  73. <el-input v-model="skuForm.brand" :minlength="2" :maxlength="20" :disabled="disabled" clearable placeholder="请输入品牌"></el-input>
  74. </el-form-item>
  75. </el-col>
  76. <el-col :span="10">
  77. <el-form-item label="条码:" prop="bar_code">
  78. <el-input v-model="skuForm.bar_code" :minlength="2" :maxlength="20" :disabled="disabled" clearable placeholder="请输入条码"></el-input>
  79. </el-form-item>
  80. </el-col>
  81. <el-col :span="10">
  82. <el-form-item label="sku:" prop="sku">
  83. <el-input v-model="skuForm.sku" :minlength="2" :maxlength="20" :disabled="disabled" clearable placeholder="请输入sku"></el-input>
  84. </el-form-item>
  85. </el-col>
  86. <el-col :span="10">
  87. <el-form-item label="重量:" prop="weight">
  88. <el-input v-model="skuForm.weight" :minlength="2" :maxlength="20" :disabled="disabled" clearable placeholder="请输入重量"></el-input>
  89. </el-form-item>
  90. </el-col>
  91. <el-col :span="10">
  92. <el-form-item label="单位:" prop="unit">
  93. <el-input v-model="skuForm.unit" :minlength="2" :maxlength="20" :disabled="disabled" clearable placeholder="请输入单位"></el-input>
  94. </el-form-item>
  95. </el-col>
  96. <el-col :span="10">
  97. <el-form-item label="产品图片:" prop="image">
  98. <el-upload
  99. class="avatar-uploader"
  100. :action=uploadUrl
  101. :show-file-list="false"
  102. :disabled="disabled"
  103. :on-success="handleAvatarSuccess"
  104. :before-upload="beforeAvatarUpload"
  105. >
  106. <img v-if="skuForm.image" :src="skuForm.image" class="avatar w-28 h-28" />
  107. <el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon>
  108. </el-upload>
  109. </el-form-item>
  110. </el-col>
  111. </el-row>
  112. </el-form>
  113. <template #footer>
  114. <div class="dialog-footer">
  115. <el-button @click="dialogVisible = false">取 消</el-button>
  116. <el-button type="primary" @click="submitWarehouseForm">确 定</el-button>
  117. </div>
  118. </template>
  119. </el-dialog>
  120. <!-- <el-dialog title="续费" v-model="renewVisible" :modal-append-to-body="false" width="450px" :close-on-click-modal="false" :close-on-press-escape="false">
  121. <el-form :model="packageForm" :rules="stockRules" ref="packageFormRef" label-width="140px">
  122. <el-form-item label="套餐:" prop="company_package_id">
  123. <el-select v-model="packageForm.company_package_id" clearable placeholder="请选择套餐">
  124. <el-option v-for="item in packageList" :key="item.id" :label="item.name" :value="item.id" />
  125. </el-select>
  126. </el-form-item>
  127. </el-form>
  128. <template #footer>
  129. <div class="dialog-footer">
  130. <el-button @click="renewVisible = false">取 消</el-button>
  131. <el-button type="primary" @click="submitPackageForm">确 定</el-button>
  132. </div>
  133. </template>
  134. </el-dialog> -->
  135. </div>
  136. </template>
  137. <script lang="ts" setup>
  138. import { ref, onMounted } from 'vue';
  139. import { useStore } from 'vuex';
  140. import { ElMessageBox, FormInstance, ElMessage } from 'element-plus';
  141. import * as API_BasicSetting from '@/api/basicSetting';
  142. import * as API_Setting from '@/api/setting';
  143. import * as API_Company from '@/api/company';
  144. import * as API_Goods from '@/api/goods';
  145. import Storage from '@/utils/storage';
  146. import router from '@/router';
  147. import { provinceAndCityData, pcTextArr, regionData, pcaTextArr, codeToText } from 'element-china-area-data';
  148. import { Plus } from '@element-plus/icons-vue';
  149. import type { UploadProps } from 'element-plus';
  150. const handleAvatarSuccess: UploadProps['onSuccess'] = (response, uploadFile) => {
  151. console.log(response, uploadFile);
  152. skuForm.value.image = response.url; //URL.createObjectURL(uploadFile.raw!);
  153. };
  154. const uploadUrl = ref(import.meta.env.VITE_API_URL + '/uploaders');
  155. const beforeAvatarUpload: UploadProps['beforeUpload'] = (rawFile) => {
  156. if (rawFile.size / 1024 / 1024 > 10) {
  157. ElMessage.error('Avatar picture size can not exceed 10MB!');
  158. return false;
  159. }
  160. return true;
  161. };
  162. const store = useStore();
  163. const tableData = ref<any>({});
  164. const loading = ref(false);
  165. const dialogVisible = ref(false);
  166. const skuForm = ref<any>({
  167. name: '',
  168. brand: '',
  169. snCode: '',
  170. bar_code: '',
  171. sku: '',
  172. weight: '',
  173. image: '',
  174. unit: '',
  175. });
  176. const stockRules = ref<any>({
  177. name: [{ required: true, message: '请输入产品名称!', trigger: 'blur' }],
  178. brand: [{ required: true, message: '请输入品牌!', trigger: 'blur' }],
  179. snCode: [{ required: true, message: '请输入商品序列号!', trigger: 'blur' }],
  180. bar_code: [{ required: true, message: '请输入条码!', trigger: 'blur' }],
  181. sku: [{ required: true, message: '请输入sku!', trigger: 'blur' }],
  182. weight: [{ required: true, message: '请输入重量!', trigger: 'blur' }],
  183. postal_code: [{ required: true, message: '请输入单位!', trigger: 'blur' }],
  184. image: [{ required: true, message: '请输入上传产品图片!', trigger: 'blur' }],
  185. });
  186. const selectedOptions = ref<any[]>([]);
  187. const marketingList = ref<any[]>([]);
  188. const options = ref<any[]>(regionData);
  189. const params = ref({
  190. data: [],
  191. page_no: 1,
  192. page_size: 10,
  193. keyword: '',
  194. company_id: store.state.companId,
  195. });
  196. const roleArray = ref<any[]>([]);
  197. const disabled = ref(false);
  198. const renewVisible = ref(false);
  199. /* 套餐 */
  200. const packageForm = ref<any>({
  201. company_package_id: '',
  202. this_money: '',
  203. });
  204. let packageId = ref('');
  205. let companyId = ref('');
  206. const packageFormRef = ref();
  207. const handleBranch = (index: number, row: any) => {
  208. router.push({ name: 'branch' });
  209. };
  210. /* 续费 */
  211. const handleRenew = (index: number, row: any) => {
  212. packageForm.value.company_package_id = row.company_package_id;
  213. companyId.value = row.id;
  214. packageId.value = row.company_package_id;
  215. API_Company.companyPackage(row.company_package_id).then((res) => {
  216. packageForm.value.this_money = res.money;
  217. renewVisible.value = true;
  218. });
  219. };
  220. const skuFormRef = ref();
  221. const checkPermission = (permissions: string[]): boolean => {
  222. // Implement your permission check logic here
  223. return true;
  224. };
  225. const handleAddWarehouse = () => {
  226. selectedOptions.value = [];
  227. skuForm.value = {};
  228. disabled.value = false;
  229. dialogVisible.value = true;
  230. };
  231. const handleEditWarehouse = (index: number, row: any) => {
  232. skuForm.value = { ...row };
  233. disabled.value = false;
  234. selectedOptions.value = row.province;
  235. dialogVisible.value = true;
  236. };
  237. const searchEvent = (keyword: string) => {
  238. params.value = {
  239. ...params.value,
  240. keyword: keyword,
  241. };
  242. params.value.page_no = 1;
  243. GET_GoodsList();
  244. };
  245. const handlePageSizeChange = (size: number) => {
  246. params.value.page_size = size;
  247. GET_GoodsList();
  248. };
  249. const handlePageCurrentChange = (page: number) => {
  250. params.value.page_no = page;
  251. GET_GoodsList();
  252. };
  253. const handleDialogOpen = () => {
  254. setTimeout(() => {
  255. skuFormRef.value.clearValidate();
  256. });
  257. };
  258. const submitWarehouseForm = () => {
  259. skuFormRef.value.validate((valid: boolean) => {
  260. if (valid) {
  261. const { id } = skuForm.value;
  262. const params = { ...skuForm.value };
  263. if (id) {
  264. API_Goods.editProduct(id, params).then(() => {
  265. dialogVisible.value = false;
  266. ElMessage.success('修改成功!');
  267. GET_GoodsList();
  268. });
  269. } else {
  270. API_Goods.addProduct(params).then(() => {
  271. dialogVisible.value = false;
  272. ElMessage.success('添加成功!');
  273. GET_GoodsList();
  274. });
  275. }
  276. } else {
  277. ElMessage.error('表单填写有误,请核对!');
  278. /* store.dispatch('showMessage', { message: '表单填写有误,请核对!', type: 'error' }); */
  279. return false;
  280. }
  281. });
  282. };
  283. const GET_GoodsList = () => {
  284. loading.value = true;
  285. API_Goods.productList(params.value)
  286. .then((response) => {
  287. loading.value = false;
  288. tableData.value = response;
  289. })
  290. .catch(() => {
  291. loading.value = false;
  292. });
  293. };
  294. /* 删除 */
  295. const handleDelGoods = (row) => {
  296. ElMessageBox.confirm('确定要删除吗?', '提示', { type: 'warning' })
  297. .then(() => {
  298. API_Goods.delProduct(row.id).then(() => {
  299. ElMessage.success('删除成功!');
  300. GET_GoodsList();
  301. });
  302. })
  303. .catch(() => {});
  304. };
  305. const adminName = (val: string[]) => {
  306. let text = '';
  307. if (val !== undefined) {
  308. text += codeToText[val[0]];
  309. text += codeToText[val[1]];
  310. text += codeToText[val[2]];
  311. }
  312. return text;
  313. };
  314. /* 切换菜单 */
  315. const handleView = (row) => {
  316. skuForm.value = { ...row };
  317. disabled.value = true;
  318. dialogVisible.value = true;
  319. };
  320. onMounted(() => {
  321. GET_GoodsList();
  322. /* GET_MarketingList();
  323. GET_PackageList(); */
  324. });
  325. </script>
  326. <style>
  327. .avatar-uploader .el-upload {
  328. border: 1px dashed var(--el-border-color);
  329. border-radius: 6px;
  330. cursor: pointer;
  331. position: relative;
  332. overflow: hidden;
  333. transition: var(--el-transition-duration-fast);
  334. }
  335. .avatar-uploader .el-upload:hover {
  336. border-color: var(--el-color-primary);
  337. }
  338. .el-icon.avatar-uploader-icon {
  339. font-size: 28px;
  340. color: #8c939d;
  341. width: 112px;
  342. height: 112px;
  343. text-align: center;
  344. }
  345. </style>