| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171 |
- import { DropdownDirective } from '../shared/dropdown.directive';
- import { CommonModule } from '@angular/common';
- import { ChangeDetectionStrategy, Component, OnInit, inject, signal } from '@angular/core';
- import { FormsModule } from '@angular/forms';
- import { RouterLink } from '@angular/router';
- import { Building2, ChevronLeft, ChevronRight, Eye, Pencil, Plus, RefreshCw, Search, Trash2, Users, X } from 'lucide-angular';
- import { LucideAngularModule } from 'lucide-angular';
- import { StorePage, StoreSummary } from '../admin.models';
- import { OperationsService } from '../operations.service';
- @Component({
- selector: 'app-operations-stores',
- standalone: true,
- imports: [DropdownDirective, CommonModule, FormsModule, RouterLink, LucideAngularModule],
- templateUrl: './operations-stores.component.html',
- styleUrls: ['./operations-professional.scss', './operations-stores.component.scss'],
- changeDetection: ChangeDetectionStrategy.OnPush,
- })
- export class OperationsStoresComponent implements OnInit {
- readonly page = signal<StorePage | null>(null);
- readonly query = signal('');
- readonly status = signal('all');
- readonly loading = signal(true);
- readonly saving = signal(false);
- readonly error = signal('');
- readonly message = signal('');
- readonly drawerOpen = signal(false);
- readonly editing = signal<StoreSummary | null>(null);
- readonly deleteArmed = signal(false);
- readonly username = signal('');
- readonly password = signal('');
- readonly storeName = signal('');
- readonly contactName = signal('');
- readonly mobile = signal('');
- readonly parentStoreId = signal(0);
- readonly disabled = signal(false);
- readonly reason = signal('');
- readonly icons = { Building2, ChevronLeft, ChevronRight, Eye, Pencil, Plus, RefreshCw, Search, Trash2, Users, X };
- private readonly operations = inject(OperationsService);
- ngOnInit(): void { void this.load(1); }
- async load(page = 1): Promise<void> {
- this.loading.set(true);
- this.error.set('');
- try {
- this.page.set(await this.operations.stores(page, 20, this.query(), { status: this.status() }));
- } catch (error) {
- this.error.set(error instanceof Error ? error.message : '门店数据加载失败');
- } finally {
- this.loading.set(false);
- }
- }
- reset(): void {
- this.query.set('');
- this.status.set('all');
- void this.load(1);
- }
- pageCount(): number { return Math.max(1, Math.ceil((this.page()?.total || 0) / (this.page()?.pageSize || 20))); }
- availableParents() {
- const ownId = this.editing()?.userId || 0;
- return (this.page()?.parents || []).filter((store) => store.userId !== ownId);
- }
- openCreate(): void {
- this.editing.set(null);
- this.username.set('');
- this.password.set('');
- this.storeName.set('');
- this.contactName.set('');
- this.mobile.set('');
- this.parentStoreId.set(0);
- this.disabled.set(false);
- this.reason.set('新增门店');
- this.deleteArmed.set(false);
- this.error.set('');
- this.drawerOpen.set(true);
- }
- openEdit(row: StoreSummary, deleteMode = false): void {
- if (row.readOnly) {
- this.message.set('该门店来自旧系统实时数据,持续同步落库前暂不允许在新后台单边修改。');
- return;
- }
- this.editing.set(row);
- this.username.set(row.username);
- this.password.set('');
- this.storeName.set(row.storeName);
- this.contactName.set(row.contactName || '');
- this.mobile.set(row.mobile || '');
- this.parentStoreId.set(row.parentStoreId || 0);
- this.disabled.set(row.status === 'disabled');
- this.reason.set('');
- this.deleteArmed.set(deleteMode);
- this.error.set('');
- this.drawerOpen.set(true);
- }
- closeDrawer(): void {
- this.drawerOpen.set(false);
- this.deleteArmed.set(false);
- }
- async save(): Promise<void> {
- const editing = this.editing();
- if (!this.username().trim() || !this.storeName().trim() || !this.reason().trim()) {
- this.error.set('登录账号、门店名称和操作原因必填');
- return;
- }
- if (!editing && !this.password()) {
- this.error.set('新增门店必须设置初始密码');
- return;
- }
- this.saving.set(true);
- this.error.set('');
- try {
- await this.operations.mutate(
- editing ? 'ops/stores/update' : 'ops/stores/create',
- editing?.objectId || '',
- this.reason(),
- {
- username: this.username().trim(),
- password: this.password(),
- storeName: this.storeName().trim(),
- contactName: this.contactName().trim(),
- mobile: this.mobile().trim(),
- parentStoreId: this.parentStoreId(),
- disabled: this.disabled(),
- },
- editing?.updatedAt || '',
- );
- this.message.set(editing ? '门店资料已更新' : '门店已新增');
- this.closeDrawer();
- await this.load(editing ? this.page()?.page || 1 : 1);
- } catch (error) {
- this.error.set(error instanceof Error ? error.message : '门店资料保存失败');
- } finally {
- this.saving.set(false);
- }
- }
- async remove(): Promise<void> {
- const editing = this.editing();
- if (!editing) return;
- if (!this.reason().trim()) {
- this.error.set('删除前必须填写操作原因');
- return;
- }
- if (!this.deleteArmed()) {
- this.deleteArmed.set(true);
- return;
- }
- this.saving.set(true);
- this.error.set('');
- try {
- await this.operations.mutate('ops/stores/delete', editing.objectId, this.reason(), {}, editing.updatedAt);
- this.message.set('门店已删除,历史业务数据仍保留');
- this.closeDrawer();
- await this.load(1);
- } catch (error) {
- this.error.set(error instanceof Error ? error.message : '门店删除失败');
- } finally {
- this.saving.set(false);
- }
- }
- }
|