PeriodicServiceConfig.vue 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. <template>
  2. <div class="periodic-service-config">
  3. <div class="header">
  4. <h2>周期性服务续费配置</h2>
  5. <el-button type="primary" icon="el-icon-plus" @click="openDialog()">新增配置</el-button>
  6. </div>
  7. <el-table :data="list" v-loading="loading" border stripe style="width: 100%">
  8. <el-table-column prop="id" label="ID" width="60">
  9. <template slot="header">
  10. <span class="sort-header" @click.stop="onSortClick('id', $event)">ID{{ sortIcon('id') }}</span>
  11. </template>
  12. </el-table-column>
  13. <el-table-column prop="productId" label="商品ID" width="80" />
  14. <el-table-column prop="serviceName" label="服务名称" min-width="160">
  15. <template slot="header">
  16. <span class="sort-header" @click.stop="onSortClick('serviceName', $event)">服务名称{{ sortIcon('serviceName') }}</span>
  17. </template>
  18. </el-table-column>
  19. <el-table-column prop="cycleDays" label="周期天数" width="100" />
  20. <el-table-column prop="remindBeforeDays" label="提前提醒(天)" width="120" />
  21. <el-table-column label="自动续费" width="100">
  22. <template slot-scope="scope">
  23. <el-tag :type="scope.row.autoRenew === 1 ? 'success' : 'info'" size="small">
  24. {{ scope.row.autoRenew === 1 ? '支持' : '不支持' }}
  25. </el-tag>
  26. </template>
  27. </el-table-column>
  28. <el-table-column label="状态" width="80">
  29. <template slot-scope="scope">
  30. <el-switch v-model="scope.row.enabled" :active-value="1" :inactive-value="0"
  31. @change="toggle(scope.row)" />
  32. </template>
  33. </el-table-column>
  34. <el-table-column label="操作" width="160" fixed="right">
  35. <template slot-scope="scope">
  36. <el-button type="text" size="small" @click="openDialog(scope.row)">编辑</el-button>
  37. <el-button type="text" size="small" style="color: #f56c6c"
  38. @click="handleDelete(scope.row)">删除</el-button>
  39. </template>
  40. </el-table-column>
  41. </el-table>
  42. <el-dialog :title="dialogTitle" :visible.sync="dialogVisible" width="500px" @closed="resetForm">
  43. <el-form :model="form" label-width="120px" size="small">
  44. <el-form-item label="商品ID" required>
  45. <el-input-number v-model="form.productId" :min="1" style="width: 100%" />
  46. </el-form-item>
  47. <el-form-item label="服务名称">
  48. <el-input v-model="form.serviceName" placeholder="可选,留空则使用商品名称" />
  49. </el-form-item>
  50. <el-form-item label="周期天数" required>
  51. <el-input-number v-model="form.cycleDays" :min="1" :max="3650" style="width: 100%" />
  52. </el-form-item>
  53. <el-form-item label="提前提醒天数">
  54. <el-input-number v-model="form.remindBeforeDays" :min="1" :max="180" style="width: 100%" />
  55. </el-form-item>
  56. <el-form-item label="自动续费">
  57. <el-switch v-model="form.autoRenew" :active-value="1" :inactive-value="0" />
  58. </el-form-item>
  59. <el-form-item label="启用">
  60. <el-switch v-model="form.enabled" :active-value="1" :inactive-value="0" />
  61. </el-form-item>
  62. </el-form>
  63. <span slot="footer">
  64. <el-button @click="dialogVisible = false">取消</el-button>
  65. <el-button type="primary" :loading="submitting" @click="save">保存</el-button>
  66. </span>
  67. </el-dialog>
  68. </div>
  69. </template>
  70. <script>
  71. import { getPeriodicServiceList, createPeriodicService, updatePeriodicService, deletePeriodicService, togglePeriodicService } from '@/api/periodic-service'
  72. import SortMixin from '@/mixins/SortMixin'
  73. export default {
  74. mixins: [SortMixin],
  75. data() {
  76. return {
  77. submitting: false,
  78. loading: false,
  79. list: [],
  80. sortableColumns: { id: 'ID', serviceName: '服务名称' },
  81. dialogVisible: false,
  82. dialogTitle: '',
  83. form: {
  84. productId: null,
  85. serviceName: '',
  86. cycleDays: 365,
  87. remindBeforeDays: 30,
  88. autoRenew: 0,
  89. enabled: 1
  90. },
  91. editingId: null
  92. }
  93. },
  94. mounted() {
  95. this.fetchList()
  96. },
  97. methods: {
  98. loadList() {
  99. this.fetchList()
  100. },
  101. async fetchList() {
  102. this.loading = true
  103. try {
  104. const params = {}
  105. if (this.sortState.length > 0) params.sort = this.sortState
  106. const res = await getPeriodicServiceList(params)
  107. if (res.data && res.data.code === 200) {
  108. this.list = res.data.data || []
  109. }
  110. } catch (e) {
  111. console.error('获取列表失败', e)
  112. } finally {
  113. this.loading = false
  114. }
  115. },
  116. openDialog(row) {
  117. if (row && row.id) {
  118. this.editingId = row.id
  119. this.dialogTitle = '编辑周期性服务配置'
  120. this.form = {
  121. productId: row.productId,
  122. serviceName: row.serviceName || '',
  123. cycleDays: row.cycleDays,
  124. remindBeforeDays: row.remindBeforeDays,
  125. autoRenew: row.autoRenew,
  126. enabled: row.enabled
  127. }
  128. } else {
  129. this.editingId = null
  130. this.dialogTitle = '新增周期性服务配置'
  131. this.resetForm()
  132. }
  133. this.dialogVisible = true
  134. },
  135. resetForm() {
  136. this.form = {
  137. productId: null,
  138. serviceName: '',
  139. cycleDays: 365,
  140. remindBeforeDays: 30,
  141. autoRenew: 0,
  142. enabled: 1
  143. }
  144. },
  145. async save() {
  146. if (!this.form.productId) {
  147. this.$message.error('请输入商品ID')
  148. return
  149. }
  150. if (!this.form.cycleDays || this.form.cycleDays < 1) {
  151. this.$message.error('请输入有效的周期天数')
  152. return
  153. }
  154. try {
  155. let res
  156. if (this.editingId) {
  157. res = await updatePeriodicService({ id: this.editingId, ...this.form })
  158. } else {
  159. res = await createPeriodicService(this.form)
  160. }
  161. if (res.data && res.data.code === 200) {
  162. this.$message.success(this.editingId ? '更新成功' : '创建成功')
  163. this.dialogVisible = false
  164. this.fetchList()
  165. } else {
  166. this.$message.error(res.data?.message || '操作失败')
  167. }
  168. } catch (e) {
  169. this.$message.error('操作失败')
  170. }
  171. },
  172. async toggle(row) {
  173. try {
  174. const res = await togglePeriodicService({ id: row.id })
  175. if (res.data && res.data.code === 200) {
  176. this.$message.success(res.data.message || '操作成功')
  177. }
  178. } catch (e) {
  179. this.$message.error('操作失败')
  180. row.enabled = row.enabled === 1 ? 0 : 1
  181. }
  182. },
  183. handleDelete(row) {
  184. this.$confirm('确定删除该配置吗?', '提示', { type: 'warning' }).then(async () => {
  185. try {
  186. const res = await deletePeriodicService({ id: row.id })
  187. if (res.data && res.data.code === 200) {
  188. this.$message.success('删除成功')
  189. this.fetchList()
  190. }
  191. } catch (e) {
  192. this.$message.error('删除失败')
  193. }
  194. }).catch(() => {})
  195. }
  196. }
  197. }
  198. </script>
  199. <style scoped>
  200. .periodic-service-config {
  201. padding: 20px;
  202. }
  203. .header {
  204. display: flex;
  205. justify-content: space-between;
  206. align-items: center;
  207. margin-bottom: 20px;
  208. }
  209. .sort-header {
  210. cursor: pointer;
  211. user-select: none;
  212. font-weight: 500;
  213. font-size: 12px;
  214. }
  215. .sort-header:hover {
  216. color: #409eff;
  217. }
  218. </style>